[IMP] mass_mailing: finishing refactoring for the new func flow.
- cleaned reply-to management, now displaying an alert but simplifying the underlying model about options available / not available for certain documents; - cleaned a bit the form view; - date -> create_date, and added a sent_date to distinguish the two; - removed dead code; - first draft of improving the chardomain widget bzr revid: tde@openerp.com-20140415092503-q1hku1rh12ldy9i1
This commit is contained in:
parent
48d7a6fa6c
commit
6179d9b6a2
|
@ -227,9 +227,9 @@ class MassMailing(osv.Model):
|
|||
_description = 'Mass Mailing'
|
||||
# number of periods for tracking mail_mail statistics
|
||||
_period_number = 6
|
||||
_order = 'date DESC'
|
||||
_order = 'sent_date DESC'
|
||||
|
||||
def __get_bar_values(self, cr, uid, id, obj, domain, read_fields, value_field, groupby_field, context=None):
|
||||
def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, date_begin, context=None):
|
||||
""" Generic method to generate data for bar chart values using SparklineBarWidget.
|
||||
This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
|
||||
|
||||
|
@ -245,7 +245,7 @@ class MassMailing(osv.Model):
|
|||
}
|
||||
]
|
||||
"""
|
||||
date_begin = datetime.strptime(self.browse(cr, uid, id, context=context).date, tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
|
||||
date_begin = date_begin.date()
|
||||
section_result = [{'value': 0,
|
||||
'tooltip': (date_begin + relativedelta.relativedelta(days=i)).strftime('%d %B %Y'),
|
||||
} for i in range(0, self._period_number)]
|
||||
|
@ -264,16 +264,17 @@ class MassMailing(osv.Model):
|
|||
results for the next 6 days following the mass mailing date. """
|
||||
obj = self.pool['mail.mail.statistics']
|
||||
res = {}
|
||||
for id in ids:
|
||||
res[id] = {}
|
||||
date_begin = datetime.strptime(self.browse(cr, uid, id, context=context).date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
for mailing in self.browse(cr, uid, ids, context=context):
|
||||
res[mailing.id] = {}
|
||||
date = mailing.sent_date if mailing.sent_date else mailing.create_date
|
||||
date_begin = datetime.strptime(date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
date_end = date_begin + relativedelta.relativedelta(days=self._period_number - 1)
|
||||
date_begin_str = date_begin.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
date_end_str = date_end.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
domain = [('mass_mailing_id', '=', id), ('opened', '>=', date_begin_str), ('opened', '<=', date_end_str)]
|
||||
res[id]['opened_dayly'] = json.dumps(self.__get_bar_values(cr, uid, id, obj, domain, ['opened'], 'opened_count', 'opened:day', context=context))
|
||||
domain = [('mass_mailing_id', '=', id), ('replied', '>=', date_begin_str), ('replied', '<=', date_end_str)]
|
||||
res[id]['replied_dayly'] = json.dumps(self.__get_bar_values(cr, uid, id, obj, domain, ['replied'], 'replied_count', 'replied:day', context=context))
|
||||
domain = [('mass_mailing_id', '=', mailing.id), ('opened', '>=', date_begin_str), ('opened', '<=', date_end_str)]
|
||||
res[mailing.id]['opened_dayly'] = json.dumps(self.__get_bar_values(cr, uid, obj, domain, ['opened'], 'opened_count', 'opened:day', date_begin, context=context))
|
||||
domain = [('mass_mailing_id', '=', mailing.id), ('replied', '>=', date_begin_str), ('replied', '<=', date_end_str)]
|
||||
res[mailing.id]['replied_dayly'] = json.dumps(self.__get_bar_values(cr, uid, obj, domain, ['replied'], 'replied_count', 'replied:day', date_begin, context=context))
|
||||
return res
|
||||
|
||||
def _get_statistics(self, cr, uid, ids, name, arg, context=None):
|
||||
|
@ -298,15 +299,6 @@ class MassMailing(osv.Model):
|
|||
results[mid]['replied_ratio'] = 100.0 * results[mid]['replied'] / (results[mid]['sent'] or 1)
|
||||
return results
|
||||
|
||||
def _get_private_models(self, context=None):
|
||||
return ['res.partner', 'mail.mass_mailing.contact']
|
||||
|
||||
def _get_auto_reply_to_available(self, cr, uid, ids, name, arg, context=None):
|
||||
res = dict.fromkeys(ids, False)
|
||||
for mailing in self.browse(cr, uid, ids, context=context):
|
||||
res[mailing.id] = mailing.mailing_model not in self._get_private_models(context=context)
|
||||
return res
|
||||
|
||||
def _get_mailing_model(self, cr, uid, context=None):
|
||||
return [
|
||||
('res.partner', _('Customers')),
|
||||
|
@ -319,7 +311,8 @@ class MassMailing(osv.Model):
|
|||
_columns = {
|
||||
'name': fields.char('Subject', required=True),
|
||||
'email_from': fields.char('From', required=True),
|
||||
'date': fields.datetime('Date'),
|
||||
'create_date': fields.datetime('Creation Date'),
|
||||
'sent_date': fields.datetime('Sent Date'),
|
||||
'body_html': fields.html('Body'),
|
||||
'mass_mailing_campaign_id': fields.many2one(
|
||||
'mail.mass_mailing.campaign', 'Mass Mailing Campaign',
|
||||
|
@ -334,15 +327,12 @@ class MassMailing(osv.Model):
|
|||
type='integer', string='Color Index',
|
||||
),
|
||||
# mailing options
|
||||
# TODO: simplify these 4 fields
|
||||
'reply_in_thread': fields.boolean('Reply in thread'),
|
||||
'reply_specified': fields.boolean('Specific Reply-To'),
|
||||
'auto_reply_to_available': fields.function(
|
||||
_get_auto_reply_to_available,
|
||||
type='boolean', string='Reply in thread available'
|
||||
'reply_to_mode': fields.selection(
|
||||
[('thread', 'In Document'), ('email', 'Specified Email Address')],
|
||||
string='Reply-To Mode', required=True,
|
||||
),
|
||||
'reply_to': fields.char('Reply To'),
|
||||
# Target Emails
|
||||
'reply_to': fields.char('Reply To', help='Preferred Reply-To Address'),
|
||||
# recipients
|
||||
'mailing_model': fields.selection(_mailing_model, string='Recipients Model', required=True),
|
||||
'mailing_domain': fields.char('Domain'),
|
||||
'contact_list_ids': fields.many2many(
|
||||
|
@ -412,13 +402,23 @@ class MassMailing(osv.Model):
|
|||
_get_daily_statistics, string='Replied',
|
||||
type='char', multi='_get_daily_statistics',
|
||||
oldname='replied_monthly',
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
res = super(MassMailing, self).default_get(cr, uid, fields, context=context)
|
||||
if 'reply_to_mode' in fields and not 'reply_to_mode' in res and res.get('mailing_model'):
|
||||
if res['mailing_model'] in ['res.partner', 'mail.mass_mailing.contact']:
|
||||
res['reply_to_mode'] = 'email'
|
||||
else:
|
||||
res['reply_to_mode'] = 'thread'
|
||||
return res
|
||||
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
'date': fields.datetime.now,
|
||||
'create_date': fields.datetime.now,
|
||||
'email_from': lambda self, cr, uid, ctx=None: self.pool['mail.message']._get_default_from(cr, uid, context=ctx),
|
||||
'reply_to': lambda self, cr, uid, ctx=None: self.pool['mail.message']._get_default_from(cr, uid, context=ctx),
|
||||
'mailing_model': 'mail.mass_mailing.contact',
|
||||
'contact_ab_pc': 100,
|
||||
}
|
||||
|
@ -468,42 +468,18 @@ class MassMailing(osv.Model):
|
|||
# Views & Actions
|
||||
#------------------------------------------------------
|
||||
|
||||
def on_change_model(self, cr, uid, ids, mailing_model, list_ids, context=None):
|
||||
def on_change_model_and_list(self, cr, uid, ids, mailing_model, list_ids, context=None):
|
||||
value = {}
|
||||
if mailing_model is 'mail.mass_mailing.contact':
|
||||
if list_ids and list_ids[0][0] == 6 and list_ids[0][2]:
|
||||
value['mailing_domain'] = "[('list_id', 'in', ["+','.join(map(str, list_ids[0][2]))+"])]"
|
||||
if mailing_model == 'mail.mass_mailing.contact':
|
||||
list_ids = map(lambda item: item if isinstance(item, (int, long)) else [lid for lid in item[2]], list_ids)
|
||||
if list_ids:
|
||||
value['mailing_domain'] = "[('list_id', 'in', %s)]" % list_ids
|
||||
else:
|
||||
value['mailing_domain'] = "[('list_id', '=', False)]"
|
||||
else:
|
||||
value['mailing_domain'] = False
|
||||
return {'value': value}
|
||||
|
||||
def on_change_reply_specified(self, cr, uid, ids, reply_specified, reply_in_thread, context=None):
|
||||
if reply_specified == reply_in_thread:
|
||||
return {'value': {'reply_in_thread': not reply_specified}}
|
||||
return {}
|
||||
|
||||
def on_change_reply_in_thread(self, cr, uid, ids, reply_specified, reply_in_thread, context=None):
|
||||
if reply_in_thread == reply_specified:
|
||||
return {'value': {'reply_specified': not reply_in_thread}}
|
||||
return {}
|
||||
|
||||
def on_change_contact_list_ids(self, cr, uid, ids, mailing_model, contact_list_ids, context=None):
|
||||
values = {}
|
||||
list_ids = []
|
||||
for command in contact_list_ids:
|
||||
if command[0] == 6:
|
||||
list_ids += command[2]
|
||||
if list_ids:
|
||||
values['contact_nbr'] = self.pool[mailing_model].search(
|
||||
cr, uid, [('list_id', 'in', list_ids), ('opt_out', '!=', True)],
|
||||
count=True, context=context
|
||||
)
|
||||
else:
|
||||
values['contact_nbr'] = 0
|
||||
return {'value': values}
|
||||
|
||||
def action_duplicate(self, cr, uid, ids, context=None):
|
||||
copy_id = None
|
||||
for mid in ids:
|
||||
|
@ -530,23 +506,9 @@ class MassMailing(osv.Model):
|
|||
'context': ctx,
|
||||
}
|
||||
|
||||
def action_see_recipients(self, cr, uid, ids, context=None):
|
||||
mailing = self.browse(cr, uid, ids[0], context=context)
|
||||
domain = self.pool['mail.mass_mailing.list'].get_global_domain(cr, uid, [c.id for c in mailing.contact_list_ids], context=context)[mailing.mailing_model]
|
||||
return {
|
||||
'name': _('See Recipients'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': mailing.mailing_model,
|
||||
'target': 'new',
|
||||
'domain': domain,
|
||||
'context': context,
|
||||
}
|
||||
|
||||
def action_edit_html(self, cr, uid, ids, context=None):
|
||||
# fixme: assert is not correct
|
||||
assert len(ids)==1, "One and only one ID allowed for this action"
|
||||
if not len(ids) == 1:
|
||||
raise ValueError('One and only one ID allowed for this action')
|
||||
mail = self.browse(cr, uid, ids[0], context=context)
|
||||
url = '/website_mail/email_designer?model=mail.mass_mailing&res_id=%d&field_body=body_html&field_from=email_form&field_subject=name&template_model=%s' % (ids[0], mail.mailing_model)
|
||||
return {
|
||||
|
@ -622,5 +584,5 @@ class MassMailing(osv.Model):
|
|||
composer_values['reply_to'] = mailing.reply_to
|
||||
composer_id = self.pool['mail.compose.message'].create(cr, uid, composer_values, context=comp_ctx)
|
||||
self.pool['mail.compose.message'].send_mail(cr, uid, [composer_id], context=comp_ctx)
|
||||
self.write(cr, uid, [mailing.id], {'date': fields.datetime.now(), 'state': 'done'}, context=context)
|
||||
self.write(cr, uid, [mailing.id], {'sent_date': fields.datetime.now(), 'state': 'done'}, context=context)
|
||||
return True
|
||||
|
|
|
@ -24,7 +24,7 @@ class MassMailingnReport(osv.Model):
|
|||
SELECT
|
||||
id,
|
||||
|
||||
date_trunc('day', m.date) as mailing_date
|
||||
date_trunc('day', m.sent_date) as mailing_date
|
||||
FROM
|
||||
mail_mass_mailing m
|
||||
)""")
|
||||
|
|
|
@ -16,17 +16,28 @@ openerp.mass_mailing = function (instance) {
|
|||
init: function(field_manager, node) {
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
initialize_content: function () {
|
||||
this.on("change:effective_readonly", this, this.render_value);
|
||||
},
|
||||
start: function() {
|
||||
var self=this;
|
||||
this._super.apply(this, arguments);
|
||||
$('button.select_records', this.$el).on('click', self.on_click);
|
||||
this.set_button();
|
||||
},
|
||||
render_value: function () {
|
||||
console.log('cacaprout', this.$('.select_records'));
|
||||
var self = this;
|
||||
this.$('.select_records').toggle(! this.get('effective_readonly'));
|
||||
},
|
||||
set_value: function(value_) {
|
||||
var self = this;
|
||||
this.set('value', value_ || false);
|
||||
this.set_button();
|
||||
},
|
||||
set_button: function() {
|
||||
var self = this;
|
||||
// debugger
|
||||
if (this.get('value')) {
|
||||
// TODO: rpc to copute X
|
||||
var domain = instance.web.pyeval.eval('domain', this.get('value'));
|
||||
var relation = this.getParent().fields.mailing_model.get('value')[0];
|
||||
var ds = new instance.web.DataSetStatic(self, relation, self.build_context());
|
||||
|
@ -40,32 +51,35 @@ openerp.mass_mailing = function (instance) {
|
|||
};
|
||||
},
|
||||
on_click: function(ev) {
|
||||
console.log(this.get('effective_readonly'));
|
||||
var self = this;
|
||||
var model = this.options.model || this.field_manager.get_field_value(this.options.model_field);
|
||||
this.pop = new instance.web.form.SelectCreatePopup(this);
|
||||
this.pop.select_element(
|
||||
model, {title: 'Select records...'},
|
||||
[], this.build_context());
|
||||
this.pop.on("elements_selected", self, function() {
|
||||
var self2 = this;
|
||||
var search_data = this.pop.searchview.build_search_data()
|
||||
instance.web.pyeval.eval_domains_and_contexts({
|
||||
this.pop.on("elements_selected", self, function(element_ids) {
|
||||
if (this.pop.$('input.oe_list_record_selector').prop('checked')) {
|
||||
var search_data = this.pop.searchview.build_search_data();
|
||||
var domain_done = instance.web.pyeval.eval_domains_and_contexts({
|
||||
domains: search_data.domains,
|
||||
contexts: search_data.contexts,
|
||||
group_by_seq: search_data.groupbys || []
|
||||
}).then(function (results) {
|
||||
// if selected IDS change domain
|
||||
var domain = self2.pop.dataset.domain.concat(results.domain || []);
|
||||
return results.domain;
|
||||
});
|
||||
}
|
||||
else {
|
||||
var domain = ["id", "in", element_ids];
|
||||
var domain_done = $.Deferred().resolve(domain);
|
||||
}
|
||||
$.when(domain_done).then(function (domain) {
|
||||
var domain = self.pop.dataset.domain.concat(domain || []);
|
||||
self.set_value(JSON.stringify(domain))
|
||||
});
|
||||
});
|
||||
event.preventDefault();
|
||||
},
|
||||
set_value: function(value_) {
|
||||
var self = this;
|
||||
this.set('value', value_ || false);
|
||||
this.set_button();
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.form.widgets = instance.web.form.widgets.extend(
|
||||
|
|
|
@ -232,10 +232,9 @@
|
|||
<label for="mailing_model" string="Recipients"/>
|
||||
<div>
|
||||
<field name="mailing_model" widget="radio" style="margin-bottom: 8px"
|
||||
on_change="on_change_model(mailing_model, contact_list_ids)"/>
|
||||
on_change="on_change_model_and_list(mailing_model, contact_list_ids)"/>
|
||||
|
||||
<field name="mailing_domain" widget="char_domain"
|
||||
attrs="{'invisible': [('mailing_model', '=', 'mail.mass_mailing.contact')]}"
|
||||
placeholder="Select recipients"
|
||||
options="{'model_field': 'mailing_model'}"/>
|
||||
|
||||
|
@ -243,7 +242,7 @@
|
|||
<label for="contact_list_ids" string="Select mailing lists:" class="oe_edit_only"/>
|
||||
<field name="contact_list_ids" widget="many2many_tags"
|
||||
placeholder="Select mailing lists..." class="oe_inline"
|
||||
on_change="on_change_model(mailing_model, contact_list_ids)"/>
|
||||
on_change="on_change_model_and_list(mailing_model, contact_list_ids)"/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
|
@ -260,33 +259,26 @@
|
|||
</page>
|
||||
<page string="Options">
|
||||
<group>
|
||||
<group string="Campaign" groups="mass_mailing.group_mass_mailing_campaign">
|
||||
<field name="mass_mailing_campaign_id"/>
|
||||
<label for="contact_ab_pc"/>
|
||||
<div>
|
||||
<field name="contact_ab_pc" class="oe_inline"/> %
|
||||
</div>
|
||||
</group><group>
|
||||
<field name="date"/>
|
||||
</group><group>
|
||||
<group string="Mailing">
|
||||
<label for="reply_to"/>
|
||||
<div>
|
||||
<field name="auto_reply_to_available" invisible="1"/>
|
||||
<field name="reply_in_thread" class="oe_inline"
|
||||
on_change="on_change_reply_in_thread(reply_specified, reply_in_thread, context)"
|
||||
attrs="{'readonly': [('auto_reply_to_available', '=', False)]}"/>
|
||||
<span attrs="{'invisible': [('auto_reply_to_available', '=', False)]}">
|
||||
Replies go into the original document
|
||||
</span>
|
||||
<span class="oe_grey" attrs="{'invisible': [('auto_reply_to_available', '=', True)]}">
|
||||
Replies go into the original document (not available for those recipients)
|
||||
</span>
|
||||
<br />
|
||||
<field name="reply_specified" class="oe_inline"
|
||||
on_change="on_change_reply_specified(reply_specified, reply_in_thread, context)"/> Use a specific reply-to address
|
||||
<field name="reply_to" class="oe_inline"
|
||||
style="margin-left: 8px;"
|
||||
attrs="{'required': [('reply_specified', '=', True)]}"/>
|
||||
<p class="alert alert-danger"
|
||||
attrs="{'invisible': ['|', ('reply_to_mode', '!=', 'thread'), ('mailing_model', 'not in', ['mail.mass_mailing.contact', 'res.partner'])]}">
|
||||
This option is not available for the recipients you selected.
|
||||
Please use a specific reply-to email address.
|
||||
</p>
|
||||
<field name="reply_to_mode" widget="radio"/>
|
||||
<field name="reply_to" style="margin-left: 16px;"
|
||||
attrs="{'required': [('reply_to_mode', '=', 'email')]}"/>
|
||||
</div>
|
||||
<field name="create_date" readonly="1"/>
|
||||
<field name="sent_date" readonly="1"/>
|
||||
</group>
|
||||
<group string="Campaign">
|
||||
<field name="mass_mailing_campaign_id" groups="mass_mailing.group_mass_mailing_campaign"/>
|
||||
<label for="contact_ab_pc" groups="mass_mailing.group_mass_mailing_campaign"/>
|
||||
<div>
|
||||
<field name="contact_ab_pc" class="oe_inline"/> %
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
|
@ -319,7 +311,7 @@
|
|||
<div>
|
||||
<h3><field name="name"/></h3>
|
||||
<h4 style="display: inline;"><field name="mass_mailing_campaign_id" groups="mass_mailing.group_mass_mailing_campaign"/></h4>
|
||||
<t t-if="record.mass_mailing_campaign_id.raw_value" groups="mass_mailing.group_mass_mailing_campaign"> - </t><field name="date"/>
|
||||
<t t-if="record.mass_mailing_campaign_id.raw_value" groups="mass_mailing.group_mass_mailing_campaign"> - </t><field name="sent_date"/>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: inline-block">
|
||||
|
@ -486,7 +478,7 @@
|
|||
<field name="mass_mailing_ids" readonly="1" string="Related Mailing(s)">
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="date"/>
|
||||
<field name="sent_date"/>
|
||||
<field name="state"/>
|
||||
<field name="delivered"/>
|
||||
<field name="opened"/>
|
||||
|
|
Loading…
Reference in New Issue