[FIX] [IMP] Second batch of fixes and small usability fixes/improvements for CRM / mailing

email_template:
- fix email_template overriding recipients even when the template is void; the convention is that void values in the template are not used, meaning that they are not relevant in the template and not that they should erase existing values,
- added _order on name on email_template, in order to ease the choosing of templates,
crm:
- fix phonecall scheduling taking the lead/opportunity description as phonecall description,
- fix phonecall scheduling Chatter message: added phonecall description into it
- improved phonecall scheduling wizard form view (type is now on the left to ease reading and updating),
- fix opt_out parameter explanations; this parameter is relevant only for mass mailing and marketing campaigns,
- added 'Available for mass mailing' (opt_out = False) filter to give users the possibility of filtering leads before performing mass mailing,
res_partner:
- fix notification_email_send field missing on res_partner form view, preventing management of email reception policy for partners,
- fix opt_out parameter explanations (field added in email_template); this parameter is relevant only for mass mailing and marketing campaigns,
- added 'Available for mass mailing' (opt_out = False) filter to give users the possibility of filtering leads before performing mass mailing,
mail_message:
- fix read/unread filters on mail_message (help of both filters were the same; string of Unread becomes To Read to be clearer)

bzr revid: tde@openerp.com-20130313131341-5pwn4g0nmbaq030p
This commit is contained in:
Thibault Delavallée 2013-03-13 14:13:41 +01:00
commit 52e47a660a
13 changed files with 84 additions and 42 deletions

View File

@ -259,7 +259,9 @@ class crm_lead(base_stage, format_address, osv.osv):
'channel_id': fields.many2one('crm.case.channel', 'Channel', help="Communication channel (mail, direct, phone, ...)"),
'contact_name': fields.char('Contact Name', size=64),
'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner company that will be created while converting the lead into opportunity', select=1),
'opt_out': fields.boolean('Opt-Out', oldname='optout', help="If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign."),
'opt_out': fields.boolean('Opt-Out', oldname='optout',
help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. "
"Filter 'Available for Mass Mailing' allows users to filter the leads when performing mass mailing."),
'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
'date_closed': fields.datetime('Closed', readonly=True),
@ -975,8 +977,8 @@ class crm_lead(base_stage, format_address, osv.osv):
through message_process.
This override updates the document according to the email.
"""
if custom_values is None: custom_values = {}
if custom_values is None:
custom_values = {}
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
defaults = {
'name': msg.get('subject') or _("No Subject"),

View File

@ -341,7 +341,11 @@
<filter string="Assigned to My Team(s)"
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
help="Leads that are assigned to any sales teams I am member of"/>
<separator/>
<separator />
<filter string="Available for mass mailing"
name='not_opt_out' domain="[('opt_out', '=', False)]"
help="Leads that did not ask not to be included in mass mailing campaigns"/>
<separator />
<group expand="0" string="Group By...">
<filter string="Salesperson" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Team" domain="[]" context="{'group_by':'section_id'}"/>

View File

@ -52,8 +52,6 @@ class crm_opportunity2phonecall(osv.osv_memory):
res.update({'categ_id': categ_id})
if 'partner_id' in fields:
res.update({'partner_id': opp.partner_id and opp.partner_id.id or False})
if 'note' in fields:
res.update({'note': opp.description})
if 'contact_name' in fields:
res.update({'contact_name': opp.partner_id and opp.partner_id.name or False})
if 'phone' in fields:

View File

@ -13,14 +13,14 @@
<group>
<field name="action"/>
<field name="name"/>
<field name="categ_id" string="Type"
widget="selection"
domain="[('object_id.model', '=', 'crm.phonecall')]"
groups="base.group_no_one"/>
<field name="date" string="Planned Date" attrs="{'invisible': [('action','=','log')]}"/>
</group>
<group>
<field name="partner_id" readonly="True"/>
<field name="categ_id" string="Type"
widget="selection"
domain="[('object_id.model', '=', 'crm.phonecall')]"
groups="base.group_no_one"/>
<field name="phone"/>
<field name="user_id" attrs="{'invisible': [('action','=','log')]}"/>
<field name="section_id" widget="selection" attrs="{'invisible': [('action','=','log')]}"/>

View File

@ -65,6 +65,7 @@ class email_template(osv.osv):
"Templates for sending email"
_name = "email.template"
_description = 'Email Templates'
_order = 'name'
def render_template(self, cr, uid, template, model, res_id, context=None):
"""Render the given template text, replace mako expressions ``${expr}``
@ -141,7 +142,9 @@ class email_template(osv.osv):
help="If checked, the user's signature will be appended to the text version "
"of the message"),
'subject': fields.char('Subject', translate=True, help="Subject (placeholders may be used here)",),
'email_from': fields.char('From', help="Sender address (placeholders may be used here)"),
'email_from': fields.char('From',
help="Sender address (placeholders may be used here). If not set, the default "
"value will be the author's email alias if configured, or email address."),
'email_to': fields.char('To (Emails)', help="Comma-separated recipient addresses (placeholders may be used here)"),
'email_recipients': fields.char('To (Partners)', help="Comma-separated ids of recipient partners (placeholders may be used here)"),
'email_cc': fields.char('Cc', help="Carbon copy recipients (placeholders may be used here)"),

View File

@ -28,7 +28,7 @@
<page string="Email Details">
<group>
<group string="Addressing">
<field name="email_from" required="1"/>
<field name="email_from"/>
<field name="email_to"/>
<field name="email_recipients"/>
<field name="email_cc"/>
@ -43,7 +43,7 @@
<field name="copyvalue"/>
</group>
<group string="Contents" colspan="2">
<field name="subject" required="1"/>
<field name="subject"/>
<field name="body_html" width="250" height="450" nolabel="1" colspan="2" placeholder="Email contents (in raw HTML format)"/>
</group>
</group>

View File

@ -19,7 +19,7 @@
#
##############################################################################
from openerp.osv import fields,osv
from openerp.osv import fields, osv
class res_partner(osv.osv):
"""Inherit res.partner to add a generic opt-out field that can be used
@ -28,8 +28,9 @@ class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'opt_out': fields.boolean('Opt-Out', help="If checked, this partner will not receive any automated email " \
"notifications, such as the availability of invoices."),
'opt_out': fields.boolean('Opt-Out',
help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. "
"Filter 'Available for Mass Mailing' allows users to filter the partners when performing mass mailing."),
}
_defaults = {

View File

@ -11,5 +11,19 @@
</xpath>
</field>
</record>
<record model="ir.ui.view" id="res_partner_opt_out_search">
<field name="name">res.partner.opt_out.search</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="arch" type="xml">
<filter string="Suppliers" position="after">
<separator />
<filter string="Available for mass mailing"
name='not_opt_out' domain="[('opt_out', '=', False)]"
help="Partners that did not ask not to be included in mass mailing campaigns" />
</filter>
</field>
</record>
</data>
</openerp>

View File

@ -80,7 +80,7 @@ class mail_compose_message(osv.TransientModel):
'datas_fname': attach_fname,
'res_model': model,
'res_id': res_id,
'type': 'binary', # override default_type from context, possibly meant for another model!
'type': 'binary', # override default_type from context, possibly meant for another model!
}
values['attachment_ids'].append(ir_attach_obj.create(cr, uid, data_attach, context=context))
else:
@ -125,19 +125,22 @@ class mail_compose_message(osv.TransientModel):
fields = ['body_html', 'subject', 'email_to', 'email_recipients', 'email_cc', 'attachments']
values = dict((field, template_values[field]) for field in fields if template_values.get(field))
values['body'] = values.pop('body_html', '')
# transform email_to, email_cc into partner_ids
values['partner_ids'] = []
# transform email_to, email_cc into partner_ids
partner_ids = set()
mails = tools.email_split(values.pop('email_to', '') + ' ' + values.pop('email_cc', ''))
for mail in mails:
partner_id = self.pool.get('res.partner').find_or_create(cr, uid, mail, context=context)
values['partner_ids'].append(partner_id)
partner_ids.add(partner_id)
email_recipients = values.pop('email_recipients', '')
if email_recipients:
for partner_id in email_recipients.split(','):
values['partner_ids'].append(int(partner_id))
values['partner_ids'] = list(set(values['partner_ids']))
if partner_id: # placeholders could generate '', 3, 2 due to some empty field values
partner_ids.add(int(partner_id))
# legacy template behavior: void values do not erase existing values and the
# related key is removed from the values dict
if partner_ids:
values['partner_ids'] = list(partner_ids)
return values

View File

@ -191,20 +191,31 @@ class mail_mail(osv.Model):
return body
def send_get_mail_reply_to(self, cr, uid, mail, partner=None, context=None):
""" Return a specific ir_email body. The main purpose of this method
is to be inherited by Portal, to add a link for signing in, in
each notification email a partner receives.
""" Return a specific ir_email reply_to.
:param browse_record mail: mail.mail browse_record
:param browse_record partner: specific recipient partner
"""
if mail.reply_to:
return mail.reply_to
if not mail.model or not mail.res_id:
return False
if not hasattr(self.pool.get(mail.model), 'message_get_reply_to'):
return False
return self.pool.get(mail.model).message_get_reply_to(cr, uid, [mail.res_id], context=context)[0]
email_reply_to = False
# if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
if mail.model and mail.res_id and hasattr(self.pool.get(mail.model), 'message_get_reply_to'):
email_reply_to = self.pool.get(mail.model).message_get_reply_to(cr, uid, [mail.res_id], context=context)[0]
# no alias reply_to -> reply_to will be the email_from, only the email part
if not email_reply_to and mail.email_from:
emails = tools.email_split(mail.email_from)
if emails:
email_reply_to = emails[0]
# format 'Document name <email_address>'
if email_reply_to and mail.model and mail.res_id:
document_name = self.pool.get(mail.model).name_get(cr, SUPERUSER_ID, [mail.res_id], context=context)[0]
if document_name:
email_reply_to = _('Followers of %s <%s>') % (document_name[1], email_reply_to)
return email_reply_to
def send_get_email_dict(self, cr, uid, mail, partner=None, context=None):
""" Return a dictionary for specific email values, depending on a

View File

@ -59,12 +59,12 @@
<field name="type"/>
<field name="author_id"/>
<field name="partner_ids"/>
<filter string="Read"
name="message_read" help="Show messages to read"
domain="[('to_read', '=', False)]"/>
<filter string="Unread"
<filter string="To Read"
name="message_unread" help="Show messages to read"
domain="[('to_read', '=', True)]"/>
<filter string="Read"
name="message_read" help="Show already read messages"
domain="[('to_read', '=', False)]"/>
<separator/>
<filter string="Comments"
name="comments" help="Comments"

View File

@ -30,13 +30,16 @@ class res_partner_mail(osv.Model):
_columns = {
'notification_email_send': fields.selection([
('all', 'All feeds'),
('comment', 'Comments and Emails'),
('email', 'Emails only'),
('none', 'Never')
], 'Receive Feeds by Email', required=True,
help="Choose in which case you want to receive an email when you "\
"receive new feeds."),
('none', 'Never'),
('email', 'Incoming Emails only'),
('comment', 'Incoming Emails and Discussions'),
('all', 'All Messages (discussions, emails, followed system notifications)'),
], 'Receive Messages by Email', required=True,
help="Policy to receive emails for new messages pushed to your personal Inbox:\n"
"- Never: no emails are sent\n"
"- Incoming Emails only: for messages received by the system via email\n"
"- Incoming Emails and Discussions: for incoming emails along with internal discussions\n"
"- All Messages: for every notification you receive in your Inbox"),
}
_defaults = {

View File

@ -7,6 +7,9 @@
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='active']" position="after">
<field name='notification_email_send'/>
</xpath>
<xpath expr="//sheet" position="after">
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>