summaryrefslogtreecommitdiff
path: root/addons/crm
diff options
context:
space:
mode:
authorStephane Wirtel <stw@openerp.com>2011-09-13 16:00:16 +0200
committerStephane Wirtel <stw@openerp.com>2011-09-13 16:00:16 +0200
commit2a59ce92e3ea35cca00a314d44556b522b3c2fa8 (patch)
tree6e7eec2157a513284e6740a95f2e39b7f04aef79 /addons/crm
parent8a2bc42c3c45b4d3c94070a29fa76636256f3da7 (diff)
parent2a40f9a4997eecc6f997ab0e43dc6334263b9cad (diff)
[MERGE] Email Framework - lp:~openerp-dev/openobject-addons/trunk-emails-unified
bzr revid: stw@openerp.com-20110913140016-zzfynrnjdaap0tfb
Diffstat (limited to 'addons/crm')
-rw-r--r--addons/crm/__openerp__.py3
-rw-r--r--addons/crm/crm.py178
-rw-r--r--addons/crm/crm_action_rule.py46
-rw-r--r--addons/crm/crm_lead.py92
-rw-r--r--addons/crm/crm_lead_view.xml179
-rw-r--r--addons/crm/crm_meeting.py15
-rw-r--r--addons/crm/crm_phonecall.py71
-rw-r--r--addons/crm/crm_view.xml2
-rw-r--r--addons/crm/report/crm_lead_report.py2
-rw-r--r--addons/crm/security/ir.model.access.csv8
-rw-r--r--addons/crm/wizard/__init__.py2
-rw-r--r--addons/crm/wizard/crm_add_note.py27
-rw-r--r--addons/crm/wizard/crm_lead_to_opportunity.py21
-rw-r--r--addons/crm/wizard/crm_merge_opportunities.py26
-rw-r--r--addons/crm/wizard/crm_send_email.py303
-rw-r--r--addons/crm/wizard/crm_send_email_view.xml154
-rw-r--r--addons/crm/wizard/mail_compose_message.py63
-rw-r--r--addons/crm/wizard/wizard_history_event.py2
18 files changed, 333 insertions, 861 deletions
diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py
index 5e812207921..c2dd5027b71 100644
--- a/addons/crm/__openerp__.py
+++ b/addons/crm/__openerp__.py
@@ -59,7 +59,7 @@ Creates a dashboard for CRM that includes:
'base_action_rule',
'base_setup',
'process',
- 'mail_gateway',
+ 'mail',
'base_calendar',
'resource',
'board'
@@ -85,7 +85,6 @@ Creates a dashboard for CRM that includes:
'wizard/crm_opportunity_to_phonecall_view.xml',
'wizard/crm_partner_to_opportunity_view.xml',
- 'wizard/crm_send_email_view.xml',
'wizard/crm_add_note_view.xml',
'wizard/crm_merge_opportunities_view.xml',
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index d745e285986..c7bc461fa1f 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -116,39 +116,12 @@ class crm_case_section(osv.osv):
('code_uniq', 'unique (code)', 'The code of the sales team must be unique !')
]
- def _check_recursion(self, cr, uid, ids, context=None):
-
- """
- Checks for recursion level for sales team
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of Sales team ids
- """
- level = 100
-
- while len(ids):
- cr.execute('select distinct parent_id from crm_case_section where id IN %s', (tuple(ids),))
- ids = filter(None, map(lambda x: x[0], cr.fetchall()))
- if not level:
- return False
- level -= 1
-
- return True
-
_constraints = [
- (_check_recursion, 'Error ! You cannot create recursive Sales team.', ['parent_id'])
+ (osv.osv._check_recursion, 'Error ! You cannot create recursive Sales team.', ['parent_id'])
]
def name_get(self, cr, uid, ids, context=None):
- """Overrides orm name_get method
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of sales team ids
- """
- if context is None:
- context = {}
+ """Overrides orm name_get method"""
if not isinstance(ids, list) :
ids = [ids]
res = []
@@ -174,13 +147,7 @@ class crm_case_categ(osv.osv):
}
def _find_object_id(self, cr, uid, context=None):
- """Finds id for case object
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values
- """
-
+ """Finds id for case object"""
object_id = context and context.get('object_id', False) or False
ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', object_id)])
return ids and ids[0]
@@ -217,6 +184,9 @@ class crm_base(object):
if not context.get('portal'):
return False
# was user.address_id.id, but address_id has been removed
+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ if hasattr(user, 'partner_address_id') and user.partner_address_id:
+ return user.partner_address_id
return False
def _get_default_partner(self, cr, uid, context=None):
@@ -228,6 +198,8 @@ class crm_base(object):
if not context.get('portal', False):
return False
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ if hasattr(user, 'partner_address_id') and user.partner_address_id:
+ return user.partner_address_id
return user.company_id.partner_id.id
def _get_default_email(self, cr, uid, context=None):
@@ -255,9 +227,9 @@ class crm_base(object):
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
"""This function returns value of partner email based on Partner Address
- @param ids: List of case IDs
- @param add: Id of Partner's address
- @email: Partner's email ID
+ :param ids: List of case IDs
+ :param add: Id of Partner's address
+ :param email: Partner's email ID
"""
if not add:
return {'value': {'email_from': False}}
@@ -269,9 +241,9 @@ class crm_base(object):
def onchange_partner_id(self, cr, uid, ids, part, email=False):
"""This function returns value of partner address based on partner
- @param ids: List of case IDs
- @param part: Partner's id
- @email: Partner's email ID
+ :param ids: List of case IDs
+ :param part: Partner's id
+ :param email: Partner's email ID
"""
data={}
if part:
@@ -282,6 +254,7 @@ class crm_base(object):
def case_open(self, cr, uid, ids, *args):
"""Opens Case
+ :param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
for case in cases:
@@ -295,7 +268,7 @@ class crm_base(object):
def case_close(self, cr, uid, ids, *args):
"""Closes Case
- @param ids: List of case Ids
+ :param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
@@ -306,7 +279,7 @@ class crm_base(object):
def case_cancel(self, cr, uid, ids, *args):
"""Cancels Case
- @param ids: List of case Ids
+ :param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
@@ -317,6 +290,7 @@ class crm_base(object):
def case_pending(self, cr, uid, ids, *args):
"""Marks case as pending
+ :param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
@@ -326,13 +300,14 @@ class crm_base(object):
def case_reset(self, cr, uid, ids, *args):
"""Resets case as draft
+ :param ids: List of case Ids
"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
self.write(cr, uid, ids, {'state': 'draft', 'active': True})
self._action(cr, uid, cases, 'draft')
return True
-
+
def _action(self, cr, uid, cases, state_to, scrit=None, context=None):
if context is None:
context = {}
@@ -394,10 +369,9 @@ class crm_case(crm_base):
return self.stage_change(cr, uid, ids, '<', 'sequence desc', context)
def copy(self, cr, uid, id, default=None, context=None):
- """ Overrides orm copy method.
- """
- if context is None:
- context = {}
+ """Overrides orm copy method to avoid copying messages,
+ as well as date_closed and date_open columns if they
+ exist."""
if default is None:
default = {}
@@ -409,19 +383,11 @@ class crm_case(crm_base):
default.update({ 'date_open': False })
return super(osv.osv, self).copy(cr, uid, id, default, context=context)
- def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=[], context=None):
- mailgate_pool = self.pool.get('mailgate.thread')
- return mailgate_pool.history(cr, uid, cases, keyword, history=history,\
- subject=subject, email=email, \
- details=details, email_from=email_from,\
- message_id=message_id, attach=attach, \
- context=context)
def case_open(self, cr, uid, ids, *args):
- """Opens Case
- """
+ """Opens Case"""
cases = self.browse(cr, uid, ids)
- self._history(cr, uid, cases, _('Open'))
+ self.message_append(cr, uid, cases, _('Open'))
for case in cases:
data = {'state': 'open', 'active': True }
if not case.user_id:
@@ -431,11 +397,10 @@ class crm_case(crm_base):
return True
def case_close(self, cr, uid, ids, *args):
- """Closes Case
- """
+ """Closes Case"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
- self._history(cr, uid, cases, _('Close'))
+ self.message_append(cr, uid, cases, _('Close'))
self.write(cr, uid, ids, {'state': 'done',
'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'),
})
@@ -446,12 +411,10 @@ class crm_case(crm_base):
return True
def case_escalate(self, cr, uid, ids, *args):
- """Escalates case to top level
- """
+ """Escalates case to parent level"""
cases = self.browse(cr, uid, ids)
for case in cases:
data = {'active': True}
-
if case.section_id.parent_id:
data['section_id'] = case.section_id.parent_id.id
if case.section_id.parent_id.change_responsible:
@@ -461,16 +424,15 @@ class crm_case(crm_base):
raise osv.except_osv(_('Error !'), _('You can not escalate, You are already at the top level regarding your sales-team category.'))
self.write(cr, uid, [case.id], data)
cases = self.browse(cr, uid, ids)
- self._history(cr, uid, cases, _('Escalate'))
+ self.message_append(cr, uid, cases, _('Escalate'))
self._action(cr, uid, cases, 'escalate')
return True
def case_cancel(self, cr, uid, ids, *args):
- """Cancels Case
- """
+ """Cancels Case"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
- self._history(cr, uid, cases, _('Cancel'))
+ self.message_append(cr, uid, cases, _('Cancel'))
self.write(cr, uid, ids, {'state': 'cancel',
'active': True})
self._action(cr, uid, cases, 'cancel')
@@ -480,56 +442,37 @@ class crm_case(crm_base):
return True
def case_pending(self, cr, uid, ids, *args):
- """Marks case as pending
- """
+ """Marks case as pending"""
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
- self._history(cr, uid, cases, _('Pending'))
+ self.message_append(cr, uid, cases, _('Pending'))
self.write(cr, uid, ids, {'state': 'pending', 'active': True})
self._action(cr, uid, cases, 'pending')
return True
def case_reset(self, cr, uid, ids, *args):
- """Resets case as draft
- """
- state = 'draft'
+ """Resets case as draft"""
+ state = 'draft'
if 'crm.phonecall' in args:
- state = 'open'
+ state = 'open'
cases = self.browse(cr, uid, ids)
cases[0].state # to fill the browse record cache
- self._history(cr, uid, cases, _('Draft'))
+ self.message_append(cr, uid, cases, _('Draft'))
self.write(cr, uid, ids, {'state': state, 'active': True})
self._action(cr, uid, cases, state)
return True
def remind_partner(self, cr, uid, ids, context=None, attach=False):
-
- """
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of Remind Partner's IDs
- @param context: A standard dictionary for contextual values
-
- """
-
return self.remind_user(cr, uid, ids, context, attach,
destination=False)
def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True):
- """
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param ids: List of case's IDs to remind
- @param context: A standard dictionary for contextual values
- """
+ mail_message = self.pool.get('mail.message')
for case in self.browse(cr, uid, ids, context=context):
if not destination and not case.email_from:
return False
if not case.user_id.user_email:
return False
-
if destination and case.section_id.user_id:
case_email = case.section_id.user_id.user_email
else:
@@ -550,37 +493,31 @@ class crm_case(crm_base):
body = self.format_body(body)
- attach_to_send = None
+ attach_to_send = {}
if attach:
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname', 'datas'])
- attach_to_send = map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send)
+ attach_to_send = dict(map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send))
- # Send an email
- subject = "Reminder: [%s] %s" % (str(case.id), case.name,)
- tools.email_send(
+ # Send an email
+ subject = "Reminder: [%s] %s" % (str(case.id), case.name, )
+ mail_message.schedule_with_attach(cr, uid,
src,
[dest],
subject,
body,
- reply_to=case.section_id.reply_to or '',
- openobject_id=str(case.id),
- attach=attach_to_send
+ model='crm.case',
+ reply_to=case.section_id.reply_to,
+ res_id=case.id,
+ attachments=attach_to_send,
+ context=context
)
- self._history(cr, uid, [case], _('Send'), history=True, subject=subject, email=dest, details=body, email_from=src)
-
return True
def _check(self, cr, uid, ids=False, context=None):
- """
- Function called by the scheduler to process cases for date actions
- Only works on not done and cancelled cases
-
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values
+ """Function called by the scheduler to process cases for date actions
+ Only works on not done and cancelled cases
"""
cr.execute('select * from crm_case \
where (date_action_last<%s or date_action_last is null) \
@@ -599,9 +536,7 @@ class crm_case(crm_base):
def format_mail(self, obj, body):
return self.pool.get('base.action.rule').format_mail(obj, body)
- def message_followers(self, cr, uid, ids, context=None):
- """ Get a list of emails of the people following this thread
- """
+ def message_thread_followers(self, cr, uid, ids, context=None):
res = {}
for case in self.browse(cr, uid, ids, context=context):
l=[]
@@ -613,12 +548,7 @@ class crm_case(crm_base):
return res
def _links_get(self, cr, uid, context=None):
- """Gets links value for reference field
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values
- """
+ """Gets links value for reference field"""
obj = self.pool.get('res.request.link')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['object', 'name'], context)
@@ -634,10 +564,8 @@ class users(osv.osv):
def create(self, cr, uid, vals, context=None):
res = super(users, self).create(cr, uid, vals, context=context)
section_obj=self.pool.get('crm.case.section')
-
- if vals.get('context_section_id', False):
+ if vals.get('context_section_id'):
section_obj.write(cr, uid, [vals['context_section_id']], {'member_ids':[(4, res)]}, context)
return res
users()
-
diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py
index 31dcc0be56a..559d257820a 100644
--- a/addons/crm/crm_action_rule.py
+++ b/addons/crm/crm_action_rule.py
@@ -40,12 +40,12 @@ class base_action_rule(osv.osv):
'regex_history' : fields.char('Regular Expression on Case History', size=128),
'act_section_id': fields.many2one('crm.case.section', 'Set Team to'),
'act_categ_id': fields.many2one('crm.case.categ', 'Set Category to'),
- 'act_mail_to_partner': fields.boolean('Mail to Partner', help="Check \
-this if you want the rule to send an email to the partner."),
+ 'act_mail_to_partner': fields.boolean('Mail to Partner',
+ help="Check this if you want the rule to send an email to the partner."),
}
-
def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from', False), context=None):
+ mail_message = self.pool.get('mail.message')
body = self.format_mail(obj, body)
if not emailfrom:
if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.user_email:
@@ -58,15 +58,10 @@ this if you want the rule to send an email to the partner."),
else:
reply_to = emailfrom
if not emailfrom:
- raise osv.except_osv(_('Error!'),
- _("No E-Mail ID Found for your Company address!"))
- return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id))
+ raise osv.except_osv(_('Error!'), _("No E-Mail Found for your Company address!"))
+ return mail_message.schedule_with_attach(cr, uid, emailfrom, emails, name, body, model='base.action.rule', reply_to=reply_to, res_id=obj.id)
def do_check(self, cr, uid, action, obj, context=None):
- """ @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values"""
ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)
if hasattr(obj, 'section_id'):
@@ -74,9 +69,8 @@ this if you want the rule to send an email to the partner."),
if hasattr(obj, 'categ_id'):
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id == obj.categ_id.id)
- #Cheking for history
+ #Cheking for history
regex = action.regex_history
- result_history = True
if regex:
res = False
ptrn = re.compile(str(regex))
@@ -85,23 +79,17 @@ this if you want the rule to send an email to the partner."),
if _result:
res = True
break
- result_history = res
- ok = ok and (not regex or result_history)
+ ok = ok and res
- res_count = True
if action.trg_max_history:
res_count = False
- history_ids = filter(lambda x: x.history, obj.message_ids)
+ history_ids = filter(lambda x: x.email_from, obj.message_ids)
if len(history_ids) <= action.trg_max_history:
res_count = True
- ok = ok and res_count
+ ok = ok and res_count
return ok
def do_action(self, cr, uid, action, model_obj, obj, context=None):
- """ @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values """
res = super(base_action_rule, self).do_action(cr, uid, action, model_obj, obj, context=context)
write = {}
@@ -118,8 +106,8 @@ this if you want the rule to send an email to the partner."),
write['email_cc'] = obj.act_email_cc
# Put state change by rule in communication history
- if hasattr(obj, 'state') and action.act_state:
- model_obj._history(cr, uid, [obj], _(action.act_state))
+ if hasattr(obj, 'state') and hasattr(obj, 'message_append') and action.act_state:
+ model_obj.message_append(cr, uid, [obj], _(action.act_state))
model_obj.write(cr, uid, [obj.id], write, context)
emails = []
@@ -134,22 +122,12 @@ this if you want the rule to send an email to the partner."),
def state_get(self, cr, uid, context=None):
- """Gets available states for crm
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values """
+ """Gets available states for crm"""
res = super(base_action_rule, self).state_get(cr, uid, context=context)
return res + crm.AVAILABLE_STATES
def priority_get(self, cr, uid, context=None):
- """@param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param context: A standard dictionary for contextual values """
res = super(base_action_rule, self).priority_get(cr, uid, context=context)
return res + crm.AVAILABLE_PRIORITIES
-base_action_rule()
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index fae37ed54a4..c409ce2aef2 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -40,7 +40,15 @@ class crm_lead(crm_case, osv.osv):
_name = "crm.lead"
_description = "Lead/Opportunity"
_order = "priority,date_action,id desc"
- _inherit = ['mailgate.thread','res.partner.address']
+ _inherit = ['mail.thread','res.partner.address']
+
+ # overridden because res.partner.address has an inconvenient name_get,
+ # especially if base_contact is installed.
+ def name_get(self, cr, user, ids, context=None):
+ if isinstance(ids, (int, long)):
+ ids = [ids]
+ return [(r['id'], tools.ustr(r[self._rec_name]))
+ for r in self.read(cr, user, ids, [self._rec_name], context)]
def _compute_day(self, cr, uid, ids, fields, args, context=None):
"""
@@ -101,8 +109,8 @@ class crm_lead(crm_case, osv.osv):
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)
+ msg_obj = self.pool.get('mail.message')
+ message_ids = msg_obj.search(cr, uid, [('email_from','!=',False), ('subject', args[0][1], args[0][2])], context=context)
lead_ids = self.search(cr, uid, [('message_ids', 'in', message_ids)], context=context)
if lead_ids:
@@ -115,8 +123,8 @@ class crm_lead(crm_case, osv.osv):
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
+ if msg.email_from:
+ res[obj.id] = msg.subject
break
return res
@@ -163,7 +171,7 @@ class crm_lead(crm_case, osv.osv):
\nIf the case is in progress the state is set to \'Open\'.\
\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)]),
+ 'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
'subjects': fields.function(_get_email_subject, fnct_search=_history_search, string='Subject of Email', type='char', size=64),
@@ -335,16 +343,14 @@ class crm_lead(crm_case, osv.osv):
}
return value
- def message_new(self, cr, uid, msg, context=None):
- """ Automatically calls when new email message arrives
- """
- mailgate_pool = self.pool.get('email.server.tools')
+ def message_new(self, cr, uid, msg, custom_values=None, context=None):
+ """Automatically calls when new email message arrives"""
+ res_id = super(crm_lead, self).message_new(cr, uid, msg, custom_values=custom_values, context=context)
+ subject = msg.get('subject') or _("No Subject")
+ body = msg.get('body_text')
- subject = msg.get('subject') or _("No Subject")
- body = msg.get('body')
msg_from = msg.get('from')
priority = msg.get('priority')
-
vals = {
'name': subject,
'email_from': msg_from,
@@ -352,45 +358,27 @@ class crm_lead(crm_case, osv.osv):
'description': body,
'user_id': False,
}
- if msg.get('priority', False):
+ if priority:
vals['priority'] = priority
+ vals.update(self.message_partner_by_email(cr, uid, msg.get('from', False)))
+ self.write(cr, uid, [res_id], vals, context)
+ return res_id
- res = mailgate_pool.get_partner(cr, uid, msg.get('from') or msg.get_unixfrom())
- if res:
- vals.update(res)
-
- res = self.create(cr, uid, vals, context)
- attachents = msg.get('attachments', [])
- for attactment in attachents or []:
- data_attach = {
- 'name': attactment,
- 'datas':binascii.b2a_base64(str(attachents.get(attactment))),
- 'datas_fname': attactment,
- 'description': 'Mail attachment',
- 'res_model': self._name,
- 'res_id': res,
- }
- self.pool.get('ir.attachment').create(cr, uid, data_attach)
-
- return res
-
- def message_update(self, cr, uid, ids, vals={}, msg="", default_act='pending', context=None):
- """
- @param ids: List of update mail’s IDs
- """
+ def message_update(self, cr, uid, ids, msg, vals={}, default_act='pending', context=None):
if isinstance(ids, (str, int, long)):
ids = [ids]
+ super(crm_lead, self).message_update(cr, uid, ids, msg, context=context)
+
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
vals['priority'] = msg.get('priority')
-
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = {}
- for line in msg['body'].split('\n'):
+ for line in msg['body_text'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower()):
@@ -408,12 +396,6 @@ class crm_lead(crm_case, osv.osv):
res = self.write(cr, uid, [case.id], values, context=context)
return res
- def msg_send(self, cr, uid, id, *args, **argv):
- """ Send The Message
- @param ids: List of email’s IDs
- """
- return True
-
def action_makeMeeting(self, cr, uid, ids, context=None):
"""
This opens Meeting's calendar view to schedule meeting on current Opportunity
@@ -459,6 +441,15 @@ class crm_lead(crm_case, osv.osv):
}
return value
+
+ def unlink(self, cr, uid, ids, context=None):
+ for lead in self.browse(cr, uid, ids, context):
+ if (not lead.section_id.allow_unlink) and (lead.state <> 'draft'):
+ raise osv.except_osv(_('Warning !'),
+ _('You can not delete this lead. You should better cancel it.'))
+ return super(crm_lead, self).unlink(cr, uid, ids, context)
+
+
def write(self, cr, uid, ids, vals, context=None):
if not context:
context = {}
@@ -468,7 +459,8 @@ class crm_lead(crm_case, osv.osv):
if 'stage_id' in vals and vals['stage_id']:
stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, vals['stage_id'], context=context)
- self.history(cr, uid, ids, _("Changed Stage to: %s") % stage_obj.name, details=_("Changed Stage to: %s") % stage_obj.name)
+ text = _("Changed Stage to: %s") % stage_obj.name
+ self.message_append(cr, uid, ids, text, body_text=text, context=context)
message=''
for case in self.browse(cr, uid, ids, context=context):
if case.type == 'lead' or context.get('stage_type',False)=='lead':
@@ -478,14 +470,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 unlink(self, cr, uid, ids, context=None):
- for lead in self.browse(cr, uid, ids, context):
- if (not lead.section_id.allow_unlink) and (lead.state <> 'draft'):
- raise osv.except_osv(_('Warning !'),
- _('You can not delete this lead. You should better cancel it.'))
- return super(crm_lead, self).unlink(cr, uid, ids, context)
-
-
crm_lead()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 0ad576fd470..f76d32b1710 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -97,10 +97,10 @@
</group>
<group colspan="2" col="3">
<separator string="Communication" colspan="4" col="3"/>
- <field name="email_from" widget="email"/><button string="Mail"
- name="%(crm.action_crm_send_mail)d"
- context="{'mail':'new', 'model': 'crm.lead'}"
- icon="terp-mail-message-new" type="action" colspan="1"/>
+ <field name="email_from" widget="email"/>
+ <button string="Mail"
+ name="%(mail.action_email_compose_message_wizard)d"
+ icon="terp-mail-message-new" type="action" colspan="1"/>
<newline/>
<field name="phone"/>
<newline/>
@@ -174,52 +174,53 @@
<group colspan="4">
<field colspan="4" name="email_cc" widget="char" size="512"/>
</group>
- <field name="message_ids" colspan="4" nolabel="1" mode="tree,form">
+ <field name="message_ids" colspan="4" nolabel="1" mode="tree,form" readonly="1">
<tree string="History">
<field name="display_text" string="History Information"/>
- <field name="history" invisible="1"/>
+ <field name="email_from" invisible="1"/>
<button
- string="Reply" attrs="{'invisible': [('history', '!=', True)]}"
- name="%(crm.action_crm_send_mail)d"
- context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
+ string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
+ name="%(mail.action_email_compose_message_wizard)d"
+ context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
icon="terp-mail-replied" type="action" />
</tree>
- <form string="History">
- <group col="4" colspan="4">
+ <form string="History">
+ <group col="4" colspan="4">
+ <group col="2" colspan="2" attrs="{'invisible': [('email_from', '=', False)]}">
<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>
+ <group col="2" colspan="2">
+ <field name="date"/>
+ <field name="email_cc" size="512" attrs="{'invisible': [('email_from', '=', False)]}"/>
+ </group>
+ <field name="subject" colspan="4" widget="char" attrs="{'invisible': [('email_from', '=', False)]}" size="512"/>
+ <field name="display_text" colspan="4" attrs="{'invisible': [('email_from', '!=', False)]}"/>
+ </group>
+ <notebook colspan="4">
+ <page string="Details" attrs="{'invisible': [('email_from', '=', False)]}">
+ <field name="body_text" colspan="4" nolabel="1"/>
+ <group attrs="{'invisible': [('email_from', '=', False)]}">
+ <button colspan="4" string="Reply"
+ name="%(mail.action_email_compose_message_wizard)d"
+ context="{'mail.compose.message.mode':'reply'}"
+ icon="terp-mail-replied" type="action"/>
+ </group>
+
+ </page>
+ <page string="Attachments" attrs="{'invisible': [('email_from', '=', False)]}">
+ <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"
context="{'model': 'crm.lead' }"
icon="terp-document-new" type="action" />
<button string="Send New Email"
- name="%(crm.action_crm_send_mail)d"
- context="{'mail':'new', 'model': 'crm.lead'}"
- icon="terp-mail-message-new" type="action" />
+ name="%(mail.action_email_compose_message_wizard)d"
+ icon="terp-mail-message-new" type="action"/>
</page>
</notebook>
</form>
@@ -324,10 +325,10 @@
<div class="oe_kanban_buttons_set oe_kanban_color_border oe_kanban_color_bglight oe_kanban_box_show_onclick">
<div class="oe_kanban_left">
+
<a string="Send New Email" class="oe_kanban_color_border"
- name="%(crm.action_crm_send_mail)d"
- context="{'mail':'new', 'model': 'crm.lead'}"
- icon="terp-mail-message-new" type="action"/>
+ name="%(mail.action_email_compose_message_wizard)d"
+ icon="terp-mail-message-new" type="action"/>
<a string="Schedule/Log Call" class="oe_kanban_color_border"
name="%(opportunity2phonecall_act)d"
@@ -492,7 +493,7 @@
<group col="3" colspan="2">
<field name="email_from" string="Email" />
<button string="Mail"
- name="%(crm.action_crm_send_mail)d"
+ name="%(mail.action_email_compose_message_wizard)d"
context="{'mail':'new', 'model': 'crm.lead'}"
icon="terp-mail-message-new" type="action" />
</group>
@@ -552,58 +553,56 @@
<field name="optout" on_change="on_change_optout(optout)"/>
</group>
</page>
-
<page string="Communication &amp; History" groups="base.group_extended">
- <group colspan="4">
- <field colspan="4" name="email_cc" string="Global CC" widget="char" size="512"/>
- </group>
- <field name="message_ids" colspan="4" nolabel="1" mode="tree,form">
- <tree string="History">
- <field name="display_text" string="History Information"/>
- <field name="history" invisible="1"/>
- <button
- string="Reply" attrs="{'invisible': [('history', '!=', True)]}"
- name="%(crm.action_crm_send_mail)d"
- context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
- icon="terp-mail-replied" type="action" />
- </tree>
- <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>
-
+ <group colspan="4">
+ <field colspan="4" name="email_cc" widget="char" size="512"/>
+ </group>
+ <field name="message_ids" colspan="4" nolabel="1" mode="tree,form" readonly="1">
+ <tree string="History">
+ <field name="display_text" string="History Information"/>
+ <field name="email_from" invisible="1"/>
+ <button
+ string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
+ name="%(mail.action_email_compose_message_wizard)d"
+ context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
+ icon="terp-mail-replied" type="action" />
+ </tree>
+ <form string="History">
+ <group col="4" colspan="4">
+ <group col="2" colspan="2" attrs="{'invisible': [('email_from', '=', False)]}">
+ <field name="email_from"/>
+ <field name="email_to" size="512"/>
+ </group>
+ <group col="2" colspan="2">
+ <field name="date"/>
+ <field name="email_cc" size="512" attrs="{'invisible': [('email_from', '=', False)]}"/>
+ </group>
+ <field name="subject" colspan="4" widget="char" attrs="{'invisible': [('email_from', '=', False)]}" size="512"/>
+ <field name="display_text" colspan="4" attrs="{'invisible': [('email_from', '!=', False)]}"/>
+ </group>
+ <notebook colspan="4">
+ <page string="Details" attrs="{'invisible': [('email_from', '=', False)]}">
+ <field name="body_text" colspan="4" nolabel="1"/>
+ <group attrs="{'invisible': [('email_from', '=', False)]}">
+ <button colspan="4" string="Reply"
+ name="%(mail.action_email_compose_message_wizard)d"
+ context="{'mail.compose.message.mode':'reply'}"
+ 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"
- context="{'model': 'crm.lead' }"
- icon="terp-document-new" type="action" />
- <button string="Send New Email"
- name="%(crm.action_crm_send_mail)d"
- context="{'mail':'new', 'model': 'crm.lead'}"
- icon="terp-mail-message-new" type="action" />
+ <page string="Attachments" attrs="{'invisible': [('email_from', '=', False)]}">
+ <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"
+ context="{'model': 'crm.lead' }"
+ icon="terp-document-new" type="action" />
+ <button string="Send New Email"
+ name="%(mail.action_email_compose_message_wizard)d"
+ icon="terp-mail-message-new" type="action"/>
</page>
<page string="Extra Info" groups="base.group_extended">
<group col="2" colspan="2">
diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py
index 4e329ddc6d4..c3381601cbf 100644
--- a/addons/crm/crm_meeting.py
+++ b/addons/crm/crm_meeting.py
@@ -45,12 +45,12 @@ class crm_meeting(crm_base, osv.osv):
_inherit = "calendar.event"
_columns = {
# From crm.case
- 'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
- 'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
+ 'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
+ 'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
- domain="[('partner_id','=',partner_id)]", states={'done': [('readonly', True)]}),
+ domain="[('partner_id','=',partner_id)]", states={'done': [('readonly', True)]}),
'section_id': fields.many2one('crm.case.section', 'Sales Team', states={'done': [('readonly', True)]}, \
- select=True, help='Sales team to which Case belongs to.'),
+ select=True, help='Sales team to which Case belongs to.'),
'email_from': fields.char('Email', size=128, states={'done': [('readonly', True)]}, help="These people will receive email."),
'id': fields.integer('ID'),
'create_date': fields.datetime('Creation Date' , readonly=True),
@@ -67,7 +67,7 @@ class crm_meeting(crm_base, osv.osv):
'event_id', 'attendee_id', 'Attendees', states={'done': [('readonly', True)]}),
'date_closed': fields.datetime('Closed', readonly=True),
'date_deadline': fields.datetime('Deadline', states={'done': [('readonly', True)]}),
- 'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
+ 'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
'state': fields.selection([('open', 'Confirmed'),
('draft', 'Unconfirmed'),
('cancel', 'Cancelled'),
@@ -75,7 +75,7 @@ class crm_meeting(crm_base, osv.osv):
size=16, readonly=True),
}
_defaults = {
- 'state': 'draft',
+ 'state': 'draft',
'active': 1,
'user_id': lambda self, cr, uid, ctx: uid,
}
@@ -138,7 +138,7 @@ class res_users(osv.osv):
def create(self, cr, uid, data, context=None):
user_id = super(res_users, self).create(cr, uid, data, context=context)
-
+
# add shortcut unless 'noshortcut' is True in context
if not(context and context.get('noshortcut', False)):
data_obj = self.pool.get('ir.model.data')
@@ -150,7 +150,6 @@ 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()
diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py
index 06c90417725..d5d7d6c5614 100644
--- a/addons/crm/crm_phonecall.py
+++ b/addons/crm/crm_phonecall.py
@@ -36,18 +36,18 @@ class crm_phonecall(crm_base, osv.osv):
# From crm.case
'id': fields.integer('ID'),
'name': fields.char('Call Summary', size=64),
- 'active': fields.boolean('Active', required=False),
+ 'active': fields.boolean('Active', required=False),
'date_action_last': fields.datetime('Last Action', readonly=1),
- 'date_action_next': fields.datetime('Next Action', readonly=1),
+ 'date_action_next': fields.datetime('Next Action', readonly=1),
'create_date': fields.datetime('Creation Date' , readonly=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
- select=True, help='Sales team to which Case belongs to.'),
- 'user_id': fields.many2one('res.users', 'Responsible'),
- 'partner_id': fields.many2one('res.partner', 'Partner'),
+ select=True, help='Sales team to which Case belongs to.'),
+ 'user_id': fields.many2one('res.users', 'Responsible'),
+ 'partner_id': fields.many2one('res.partner', 'Partner'),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
- domain="[('partner_id','=',partner_id)]"),
- 'company_id': fields.many2one('res.company', 'Company'),
- 'description': fields.text('Description'),
+ domain="[('partner_id','=',partner_id)]"),
+ 'company_id': fields.many2one('res.company', 'Company'),
+ 'description': fields.text('Description'),
'state': fields.selection([
('draft', 'Draft'),
('open', 'Todo'),
@@ -57,24 +57,24 @@ class crm_phonecall(crm_base, osv.osv):
], 'State', size=16, readonly=True,
help='The state is set to \'Todo\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
- \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\'.'),
- 'email_from': fields.char('Email', size=128, help="These people will receive email."),
+ \nWhen the call is over, the state is set to \'Held\'.\
+ \nIf the call needs to be done then the state is set to \'Not Held\'.'),
+ 'email_from': fields.char('Email', size=128, help="These people will receive email."),
'date_open': fields.datetime('Opened', readonly=True),
# phonecall fields
- 'duration': fields.float('Duration', help="Duration in Minutes"),
+ 'duration': fields.float('Duration', help="Duration in Minutes"),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="['|',('section_id','=',section_id),('section_id','=',False),\
- ('object_id.model', '=', 'crm.phonecall')]"),
- 'partner_phone': fields.char('Phone', size=32),
+ ('object_id.model', '=', 'crm.phonecall')]"),
+ 'partner_phone': fields.char('Phone', size=32),
'partner_contact': fields.related('partner_address_id', 'name', \
- type="char", string="Contact", size=128),
- 'partner_mobile': fields.char('Mobile', size=32),
- 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
+ type="char", string="Contact", size=128),
+ 'partner_mobile': fields.char('Mobile', size=32),
+ 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'date_closed': fields.datetime('Closed', readonly=True),
'date': fields.datetime('Date'),
'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
- 'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
+ 'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
}
def _get_default_state(self, cr, uid, context=None):
@@ -83,17 +83,14 @@ class crm_phonecall(crm_base, osv.osv):
return 'open'
_defaults = {
- 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
+ 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'priority': crm.AVAILABLE_PRIORITIES[2][0],
'state': _get_default_state,
'user_id': lambda self,cr,uid,ctx: uid,
- 'active': 1,
+ 'active': 1,
}
-
-
-
- # From crm.case
+ # From crm.case
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
res = super(crm_phonecall, self).onchange_partner_address_id(cr, uid, ids, add, email)
res.setdefault('value', {})
@@ -176,23 +173,23 @@ class crm_phonecall(crm_base, osv.osv):
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
context = {
- 'default_phonecall_id': phonecall.id,
- 'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
- 'default_email': phonecall.email_from ,
+ 'default_phonecall_id': phonecall.id,
+ 'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
+ 'default_email': phonecall.email_from ,
'default_name': phonecall.name
}
value = {
- 'name': _('Meetings'),
- 'domain' : "[('user_id','=',%s)]" % (uid),
- 'context': context,
- 'view_type': 'form',
- 'view_mode': 'calendar,form,tree',
- 'res_model': 'crm.meeting',
- 'view_id': False,
- 'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
- 'type': 'ir.actions.act_window',
- 'search_view_id': res['res_id'],
+ 'name': _('Meetings'),
+ 'domain' : "[('user_id','=',%s)]" % (uid),
+ 'context': context,
+ 'view_type': 'form',
+ 'view_mode': 'calendar,form,tree',
+ 'res_model': 'crm.meeting',
+ 'view_id': False,
+ 'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
+ 'type': 'ir.actions.act_window',
+ 'search_view_id': res['res_id'],
'nodestroy': True
}
diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml
index d58348a56dd..c7038958126 100644
--- a/addons/crm/crm_view.xml
+++ b/addons/crm/crm_view.xml
@@ -74,7 +74,7 @@
<notebook colspan="4">
<page string="Sales Team">
<group col="2" colspan="1">
- <separator string="Mailgateway" colspan="2"/>
+ <separator string="Mail Gateway" colspan="2"/>
<field name="reply_to" select="2"/>
</group>
<group col="2" colspan="1">
diff --git a/addons/crm/report/crm_lead_report.py b/addons/crm/report/crm_lead_report.py
index bd61e1ee80d..18615bdf344 100644
--- a/addons/crm/report/crm_lead_report.py
+++ b/addons/crm/report/crm_lead_report.py
@@ -121,7 +121,7 @@ class crm_lead_report(osv.osv):
c.planned_revenue,
c.planned_revenue*(c.probability/100) as probable_revenue,
1 as nbr,
- (SELECT count(id) FROM mailgate_message WHERE model='crm.lead' AND res_id=c.id AND history=True) AS email,
+ (SELECT count(id) FROM mail_message WHERE model='crm.lead' AND res_id=c.id AND email_from is not null) AS email,
date_trunc('day',c.create_date) as create_date,
extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as delay_close,
abs(extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24)) as delay_expected,
diff --git a/addons/crm/security/ir.model.access.csv b/addons/crm/security/ir.model.access.csv
index 6f7b3066d7a..6b0a3ac15a9 100644
--- a/addons/crm/security/ir.model.access.csv
+++ b/addons/crm/security/ir.model.access.csv
@@ -29,15 +29,15 @@
"access_res_partner_manager","res.partner.crm.manager","base.model_res_partner","base.group_sale_manager",1,0,0,0
"access_res_partner_address_manager","res.partner.address.crm.user.manager","base.model_res_partner_address","base.group_sale_manager",1,0,0,0
"access_res_partner_category_manager","res.partner.category.crm.manager","base.model_res_partner_category","base.group_sale_manager",1,0,0,0
-"mail_gateway_mailgate_message_manager","mail_gateway.mailgate.message.manager","mail_gateway.model_mailgate_message","base.group_sale_manager",1,0,0,0
-"mail_gateway_mailgate_thread_manager","mail_gateway.mailgate.thread.manager","mail_gateway.model_mailgate_thread","base.group_sale_manager",1,1,1,1
+"mail_mail_message_manager","mail.message.manager","mail.model_mail_message","base.group_sale_manager",1,0,0,0
+"mail_thread_manager","mail.thread.manager","mail.model_mail_thread","base.group_sale_manager",1,1,1,1
"access_calendar_attendee_crm_user","calendar.attendee.crm.user","model_calendar_attendee","base.group_sale_salesman",1,1,1,0
"access_calendar_attendee_crm_manager","calendar.attendee.crm.manager","model_calendar_attendee","base.group_sale_manager",1,1,1,1
"access_res_partner","res.partner.crm.user","base.model_res_partner","base.group_sale_salesman",1,1,1,0
"access_res_partner_address","res.partner.address.crm.user","base.model_res_partner_address","base.group_sale_salesman",1,1,1,0
"access_res_partner_category","res.partner.category.crm.user","base.model_res_partner_category","base.group_sale_salesman",1,1,1,0
-"mail_gateway_mailgate_thread","mail_gateway.mailgate.thread","mail_gateway.model_mailgate_thread","base.group_sale_salesman",1,1,1,1
-"mail_gateway_mailgate_message_user","mail_gateway.mailgate.message.user","mail_gateway.model_mailgate_message","base.group_sale_salesman",1,1,1,1
+"mail_mailgate_thread","mail.thread","mail.model_mail_thread","base.group_sale_salesman",1,1,1,1
+"mail_gateway_mail_message_user","mail.message.user","mail.model_mail_message","base.group_sale_salesman",1,1,1,1
"access_crm_case_categ_manager","crm.case.categ manager","model_crm_case_categ","base.group_sale_manager",1,1,1,1
"access_base_action_rule_manager","base.action.rule manager","model_base_action_rule","base.group_sale_manager",1,1,1,1
"access_crm_lead_report_user","crm.lead.report user","model_crm_lead_report","base.group_sale_salesman",1,1,1,1
diff --git a/addons/crm/wizard/__init__.py b/addons/crm/wizard/__init__.py
index 9730b8d1d55..3ebdceda437 100644
--- a/addons/crm/wizard/__init__.py
+++ b/addons/crm/wizard/__init__.py
@@ -19,7 +19,7 @@
#
##############################################################################
-import crm_send_email
+import mail_compose_message
import crm_add_note
import crm_lead_to_partner
diff --git a/addons/crm/wizard/crm_add_note.py b/addons/crm/wizard/crm_add_note.py
index 3419c89d33a..478f051fe58 100644
--- a/addons/crm/wizard/crm_add_note.py
+++ b/addons/crm/wizard/crm_add_note.py
@@ -1,11 +1,10 @@
from crm import crm
from osv import fields, osv
from tools.translate import _
-import base64
+from mail.mail_message import truncate_text
AVAILABLE_STATES = crm.AVAILABLE_STATES + [('unchanged', 'Unchanged')]
-
class crm_add_note(osv.osv_memory):
"""Adds a new note to the case."""
_name = 'crm.add.note'
@@ -14,8 +13,11 @@ class crm_add_note(osv.osv_memory):
_columns = {
'body': fields.text('Note 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'),
+ required=True),
+ }
+
+ _defaults = {
+ 'state': 'unchanged'
}
def action_add(self, cr, uid, ids, context=None):
@@ -32,14 +34,8 @@ class crm_add_note(osv.osv_memory):
case_list = case_pool.browse(cr, uid, context['active_ids'],
context=context)
case = case_list[0]
- user_obj = self.pool.get('res.users')
- user_name = user_obj.browse(cr, uid, [uid], context=context)[0].name
- attach = [
- (x.name, base64.decodestring(x.binary)) for x in obj.attachment_ids
- ]
- case_pool.history(cr, uid, [case], self.pool.get('mailgate.message').truncate_data(cr, uid, obj.body, context=context), history=False,
- details=obj.body, email_from=user_name, attach=attach)
-
+ case_pool.message_append(cr, uid, [case], truncate_text(obj.body),
+ body_text=obj.body)
if obj.state == 'unchanged':
pass
elif obj.state == 'done':
@@ -52,11 +48,4 @@ class crm_add_note(osv.osv_memory):
return {'type': 'ir.actions.act_window_close'}
- def default_get(self, cr, uid, fields, context=None):
- """
- This function gets default values
- """
- return {'state': u'unchanged'}
-
-
crm_add_note()
diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py
index 16223f8c28f..8200dbd1675 100644
--- a/addons/crm/wizard/crm_lead_to_opportunity.py
+++ b/addons/crm/wizard/crm_lead_to_opportunity.py
@@ -132,26 +132,25 @@ class crm_lead2opportunity_partner(osv.osv_memory):
vals['partner_address_id'] = False
lead.write(vals, context=context)
- leads.history(cr, uid, [lead], _('Converted to opportunity'), details='Converted to Opportunity', context=context)
+ text = _('Converted to opportunity')
+ leads.message_append(cr, uid, [lead], text, body_text=text, context=context)
if lead.partner_id:
msg_ids = [ x.id for x in lead.message_ids]
- self.pool.get('mailgate.message').write(cr, uid, msg_ids, {
+ self.pool.get('mail.message').write(cr, uid, msg_ids, {
'partner_id': lead.partner_id.id
}, 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):
+ def send_mail_to_salesman(self, cr, uid, lead):
email_to = lead.user_id and lead.user_id.user_email
if not email_to:
- return
+ return False
+ message_pool = self.pool.get('mail.message')
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
+ 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
+ body = "Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % (lead.id, lead.name, lead.partner_id.name, lead.description)
+ return message_pool.schedule_with_attach(cr, uid, email_from, [email_to], subject, body)
def action_apply(self, cr, uid, ids, context=None):
"""
@@ -205,7 +204,7 @@ class crm_lead2opportunity_partner(osv.osv_memory):
partner_id = False
self._convert(cr, uid, ids, lead, partner_id, stage_ids, context=context)
- self.send_mail_to_salesman(lead)
+ self.send_mail_to_salesman(cr, uid, 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')
diff --git a/addons/crm/wizard/crm_merge_opportunities.py b/addons/crm/wizard/crm_merge_opportunities.py
index 57620f8c016..66e8c2adbfe 100644
--- a/addons/crm/wizard/crm_merge_opportunities.py
+++ b/addons/crm/wizard/crm_merge_opportunities.py
@@ -70,9 +70,9 @@ class crm_merge_opportunity(osv.osv_memory):
return False
opps = lead_obj.browse(cr, uid, [op_id[0]], context=context)
return opps[0]
-
+
def _update_data(self, op_ids, oldest_opp):
- data = {
+ data = {
'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
@@ -105,16 +105,15 @@ class crm_merge_opportunity(osv.osv_memory):
'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),
-
- }
- return data
+ }
+ return data
def merge(self, cr, uid, op_ids, context=None):
"""
- @param opp_ids : list of opportunities ids to merge
+ :param opp_ids: list of opportunities ids to merge
"""
opp_obj = self.pool.get('crm.lead')
- message_obj = self.pool.get('mailgate.message')
+ message_obj = self.pool.get('mail.message')
lead_ids = context and context.get('lead_ids', []) or []
@@ -130,17 +129,15 @@ class crm_merge_opportunity(osv.osv_memory):
else:
first_opportunity = opportunities_list[0]
tail_opportunities = opportunities_list[1:]
-
-
data = self._update_data(op_ids, oldest_opp)
#copy message into the first opportunity + merge attachement
-
+
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:
- message_obj.write(cr, uid, history.id, {'res_id': first_opportunity.id, 'name' : _("From %s : %s") % (opp.name, history.name) }, context=context)
+ for mail_msg in opp.message_ids:
+ message_obj.write(cr, uid, mail_msg.id, {'res_id': first_opportunity.id, 'subject' : _("From %s : %s") % (opp.name, mail_msg.subject) }, context=context)
#Notification about loss of information
details = []
@@ -172,7 +169,7 @@ class crm_merge_opportunity(osv.osv_memory):
subject = subject[0] + ", ".join(subject[1:])
details = "\n\n".join(details)
- opp_obj._history(cr, uid, [first_opportunity], subject, details=details)
+ opp_obj.message_append(cr, uid, [first_opportunity], subject, body_text=details)
#data.update({'message_ids' : [(6, 0 ,self._concat_o2m('message_ids', op_ids))]})
opp_obj.write(cr, uid, [first_opportunity.id], data)
unlink_ids = map(lambda x: x.id, tail_opportunities)
@@ -180,8 +177,6 @@ class crm_merge_opportunity(osv.osv_memory):
models_data = self.pool.get('ir.model.data')
-
-
# Get Opportunity views
opportunity_view_form = models_data._get_id(
cr, uid, 'crm', 'crm_case_form_view_oppor')
@@ -216,7 +211,6 @@ class crm_merge_opportunity(osv.osv_memory):
context['lead_ids'] = [op_ids[0].id]
return self.merge(cr, uid, op_ids, context)
-
_columns = {
'opportunity_ids' : fields.many2many('crm.lead', 'merge_opportunity_rel', 'merge_id', 'opportunity_id', 'Opportunities', domain=[('type', '=', 'opportunity')]),
}
diff --git a/addons/crm/wizard/crm_send_email.py b/addons/crm/wizard/crm_send_email.py
deleted file mode 100644
index d4ba8b476a1..00000000000
--- a/addons/crm/wizard/crm_send_email.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
-# $Id$
-#
-# 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 crm import crm
-from osv import osv, fields
-from tools.translate import _
-import base64
-import itertools
-import tools
-import re
-
-
-AVAILABLE_STATES = crm.AVAILABLE_STATES + [('unchanged', 'Unchanged')]
-
-
-class crm_send_new_email_attachment(osv.osv_memory):
- _name = 'crm.send.mail.attachment'
-
- _columns = {
- 'binary' : fields.binary('Attachment', required=True),
- 'name' : fields.char('Name', size=128, required=True),
- 'wizard_id' : fields.many2one('crm.send.mail', 'Wizard', required=True),
- }
-
-crm_send_new_email_attachment()
-
-class crm_send_new_email(osv.osv_memory):
- """ Sends new email for the case"""
- _name = "crm.send.mail"
- _description = "Send new email"
-
- _columns = {
- 'email_to' : fields.char('To', size=512, required=True),
- 'email_from' : fields.char('From', size=128, required=True),
- 'reply_to' : fields.char('Reply To', size=128, required=True, help="Reply-to of the Sales team defined on this case"),
- 'email_cc' : fields.char('CC', size=512, help="These addresses will receive a copy of this email. To modify the permanent CC list, edit the global CC field of this case"),
- 'subject': fields.char('Subject', size=512, required=True),
- '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."),
- }
-
- def action_mass_send(self, cr, uid, ids, context=None):
-
- if not context:
- context = {}
-
- context.update({'mail' : 'new'})
- actives_ids = context.get('active_ids')
- 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.
- """
- hist_obj = self.pool.get('mailgate.message')
-
- if context is None:
- context = {}
-
- if not context.get('active_model'):
- raise osv.except_osv(_('Error'), _('Can not send mail!'))
-
- model = context.get('active_model')
- 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
- ]
-
- subtype = 'plain'
- message_id = None
- ref_id = None
-
- case = case_pool.browse(cr, uid, res_id, context=context)
- if context.get('mail', 'new') == 'new':
- if case.message_ids:
- message_id = case.message_ids[0].message_id
- elif context.get('mail') == 'forward':
- # extract attachements from case and emails according to mode
- attachments = []
- attach_pool = self.pool.get('ir.attachment')
- direct_attachments = attach_pool.search(cr, uid, [('res_model', '=', 'crm.lead'), ('res_id', '=', res_id)], context=context)
- attachments += attach_pool.browse(cr, uid, direct_attachments, context=context)
- if obj.history in ['latest', 'whole'] and case.message_ids:
- msgs = case.message_ids
- if obj.history == 'latest':
- msgs = msgs[:1]
- attachments.extend(itertools.chain(*[m.attachment_ids for m in msgs]))
- attach_all = [(a.datas_fname or a.name, base64.decodestring(a.datas)) for a in attachments if a.datas]
- attach += attach_all
-
- else:
- hist = hist_obj.browse(cr, uid, res_id, context=context)
- message_id = hist.message_id
- model = hist.model
- case_pool = self.pool.get(model)
- res_id = hist.res_id
- ref_id = hist.ref_id
- case = case_pool.browse(cr, uid, res_id, context=context)
-
- 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
-
- body = body and tools.ustr(body) or ''
- email_from = getattr(obj, 'email_from', False)
- x_headers = {}
- if message_id:
- x_headers['References'] = "%s" % (message_id)
-
- if obj.html:
- subtype = 'html'
-
- flag = tools.email_send(
- email_from,
- emails,
- obj.subject,
- body,
- email_cc=email_cc,
- attach=attach,
- subtype=subtype,
- reply_to=obj.reply_to,
- openobject_id=str(case.id),
- x_headers=x_headers
- )
-
- if not flag:
- raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
-
- msg_dict = {'new': 'Send', 'reply': 'Reply', 'forward': 'Forward'}
- case_pool.history(cr, uid, [case], _(msg_dict[context.get('mail', 'new')]), history=True, \
- email=obj.email_to, details=body, \
- subject=obj.subject, email_from=email_from, \
- email_cc=', '.join(email_cc), message_id=message_id, \
- references=ref_id or message_id, attach=attach)
- if obj.state == 'unchanged':
- pass
- elif obj.state == 'done':
- case_pool.case_close(cr, uid, [case.id])
- elif obj.state == 'draft':
- case_pool.case_reset(cr, uid, [case.id])
- elif obj.state in ['cancel', 'open', 'pending']:
- act = 'case_' + obj.state
- getattr(case_pool, act)(cr, uid, [case.id])
-
- return {'type': 'ir.actions.act_window_close'}
-
- def default_get(self, cr, uid, fields, context=None):
- """
- This function gets default values
- """
- if context is None:
- context = {}
-
- if not context.get('active_model'):
- raise osv.except_osv(_('Error'), _('Can not send mail!'))
-
- res = super(crm_send_new_email, self).default_get(cr, uid, fields, context=context)
-
- if context.get('mail') == 'reply':
- res.update(self.get_reply_defaults(cr, uid, fields, context=context))
- return res
-
- model = context.get('active_model')
- mod_obj = self.pool.get(model)
- res_id = context and context.get('active_ids', []) or []
-
- 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:
- if hasattr(case, 'section_id'):
- 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:
- res.update({'state': u'pending'})
-
- return res
-
- def get_reply_defaults(self, cr, uid, fields, context=None):
- """
- This function gets default values for reply mail
- """
- hist_obj = self.pool.get('mailgate.message')
- res_ids = context and context.get('active_ids', []) or []
-
- user_obj = self.pool.get('res.users')
- user_mail_from = user_obj._get_email_from(cr, uid, [uid], context=context)[uid]
-
- include_original = context and context.get('include_original', False) or False
- res = {}
- for hist in hist_obj.browse(cr, uid, res_ids, context=context):
- model = hist.model
-
- # In the case where the crm.case does not exist in the database
- if not model:
- return {'type': 'ir.actions.act_window_close'}
-
- model_pool = self.pool.get(model)
- res_id = hist.res_id
- case = model_pool.browse(cr, uid, res_id)
- if 'email_to' in fields:
- res.update({'email_to': case.email_from and tools.ustr(case.email_from) or False})
- if 'email_from' in fields:
- res.update({'email_from': user_mail_from and tools.ustr(user_mail_from) or False})
-
- signature = u'\n' + (tools.ustr(case.user_id.signature or '')) + u'\n'
- original = [signature]
-
- if include_original == True and 'body' in fields:
- header = u'-------- Original Message --------'
- sender = u'From: %s' %(tools.ustr(hist.email_from or ''))
- to = u'To: %s' % (tools.ustr(hist.email_to or ''))
- sentdate = u'Date: %s' % (tools.ustr(hist.date))
- desc = u'\n%s'%(tools.ustr(hist.description))
-
- original = [signature, header, sender, to, sentdate, desc]
-
- res['body']= u'\n' + u'\n'.join(original)
-
- if 'subject' in fields:
- res.update({u'subject': u'Re: %s' %(tools.ustr(hist.name or ''))})
- if 'email_cc' in fields:
- email_cc = (case.email_cc and tools.ustr(case.email_cc) + ', ' or '') + (hist.email_cc or '')
- res.update({'email_cc': email_cc})
- if 'reply_to' in fields:
- if hasattr(case, 'section_id'):
- res.update({'reply_to': case.section_id.reply_to or ''})
- if 'state' in fields:
- res['state'] = u'pending'
- return res
-
- def view_init(self, cr, uid, fields_list, context=None):
- """
- This function checks for precondition before wizard executes
- @param self: The object pointer
- @param cr: the current row, from the database cursor,
- @param uid: the current user’s ID for security checks,
- @param fields: List of fields for default value
- @param context: A standard dictionary for contextual values
-
- """
- if context is None:
- context = {}
-
- if not context.get('active_model'):
- raise osv.except_osv(_('Error'), _('Can not send mail!'))
- return True
-
-crm_send_new_email()
-
diff --git a/addons/crm/wizard/crm_send_email_view.xml b/addons/crm/wizard/crm_send_email_view.xml
deleted file mode 100644
index be1644b6bbb..00000000000
--- a/addons/crm/wizard/crm_send_email_view.xml
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0"?>
-<openerp>
- <data>
-
-<!-- Send New Mail view -->
-
- <record model="ir.ui.view" id="crm_send_new_mail_view">
- <field name="name">crm.new.send.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_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-close" special="cancel" />
- <button name="action_send" type="object" string="_Send" icon="gtk-go-forward" />
- </group>
- </form>
- </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">
- <field name="name">Send Mail</field>
- <field name="res_model">crm.send.mail</field>
- <field name="view_type">form</field>
- <field name="view_mode">form</field>
- <field name="view_id" ref="crm_send_new_mail_view"/>
- <field name="target">new</field>
- </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">
- <field name="name">crm.mail.reply.form</field>
- <field name="model">crm.send.mail</field>
- <field name="type">form</field>
- <field name="arch" type="xml">
- <form string="Reply to last Mail" col="2">
- <field name="email_from" />
- <field name="email_to" />
- <field name="email_cc" />
- <field name="subject" />
- <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>
- <separator string="" colspan="4"/>
- <field name="body" nolabel="1" colspan="4"/>
- <separator string=" " colspan="4"/>
- <group colspan="4" col="3" >
- <label string=" " />
- <button string="_Cancel" icon="gtk-close" special="cancel" />
- <button name="action_send" type="object" string="_Send Reply" icon="gtk-go-forward" />
- </group>
- </form>
- </field>
- </record>
-
-
-
-
-<!-- Reply to Mail action -->
-
- <record model="ir.actions.act_window" id="action_crm_reply_mail">
- <field name="name">Reply to last Mail</field>
- <field name="res_model">crm.send.mail</field>
- <field name="view_type">form</field>
- <field name="view_mode">form</field>
- <field name="view_id" ref="crm_reply_mail_view"/>
- <field name="target">new</field>
- </record>
-
- </data>
-</openerp>
diff --git a/addons/crm/wizard/mail_compose_message.py b/addons/crm/wizard/mail_compose_message.py
new file mode 100644
index 00000000000..512d9ece77a
--- /dev/null
+++ b/addons/crm/wizard/mail_compose_message.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+#
+##############################################################################
+
+from osv import osv
+from osv import fields
+import tools
+
+SUPPORTED_MODELS = ['crm.lead',]
+
+class mail_compose_message(osv.osv_memory):
+ _inherit = 'mail.compose.message'
+
+ def get_value(self, cr, uid, model, res_id, context=None):
+ """Returns a defaults-like dict with initial values for the composition
+ wizard when sending an email related to the document record identified
+ by ``model`` and ``res_id``.
+
+ Overrides the default implementation to provide more default field values
+ related to the corresponding CRM case.
+
+ :param str model: model name of the document record this mail is related to.
+ :param int res_id: id of the document record this mail is related to.
+ :param dict context: several context values will modify the behavior
+ of the wizard, cfr. the class description.
+ """
+ result = super(mail_compose_message, self).get_value(cr, uid, model, res_id, context=context)
+ if model in SUPPORTED_MODELS and res_id:
+ model_obj = self.pool.get(model)
+ data = model_obj.browse(cr, uid , res_id, context)
+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ result.update({
+ 'subject' : data.name or False,
+ 'email_to' : data.email_from or False,
+ 'email_from' : user.user_email or tools.config.get('email_from', False),
+ 'body_text' : '\n' + tools.ustr(user.signature),
+ 'email_cc' : tools.ustr(data.email_cc or ''),
+ 'model': model,
+ 'res_id': res_id,
+ 'subtype': 'plain',
+ })
+ if hasattr(data, 'section_id'):
+ result.update({'reply_to' : data.section_id and data.section_id.reply_to or False})
+ return result
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm/wizard/wizard_history_event.py b/addons/crm/wizard/wizard_history_event.py
index caaf37a88d8..bb501e0b750 100644
--- a/addons/crm/wizard/wizard_history_event.py
+++ b/addons/crm/wizard/wizard_history_event.py
@@ -32,7 +32,7 @@ def _open_history_event(self, cr, uid, data, context=None):
if id2:
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
res = ''
- if data.get('model',False) and data.get('ids',False):
+ if data.get('model') and data.get('ids'):
model_obj = pooler.get_pool(cr.dbname).get(data['model'])
res = model_obj.browse(cr, uid, data['ids'], context=context)
if len(res):