Statistics = self.pool['mail.mail.statistics']
results = dict.fromkeys(ids, False)
for cid in ids:
+ stat_ids = Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid)], context=context),
+ stats = Statistics.browse(cr, uid, stat_ids, context=context)
results[cid] = {
- 'total': Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid)], count=True, context=context),
- 'scheduled': Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid), ('scheduled', '!=', False), ('sent', '=', False)], count=True, context=context),
- 'sent': Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid), ('sent', '!=', False)], count=True, context=context),
- 'opened': Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid), ('opened', '!=', False)], count=True, context=context),
- 'replied': Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid), ('replied', '!=', False)], count=True, context=context),
- 'bounced': Statistics.search(cr, uid, [('mass_mailing_campaign_id', '=', cid), ('bounced', '!=', False)], count=True, context=context),
+ 'total': len(stats),
+ 'failed': len([s for s in stats if not s.scheduled is False and s.sent is False and not s.exception is False]),
+ 'scheduled': len([s for s in stats if not s.scheduled is False and s.sent is False]),
+ 'sent': len([s for s in stats if not s.sent is False]),
+ 'opened': len([s for s in stats if not s.opened is False]),
+ 'replied': len([s for s in stats if not s.replied is False]),
+ 'bounced': len([s for s in stats if not s.bounced is False]),
}
results[cid]['delivered'] = results[cid]['sent'] - results[cid]['bounced']
results[cid]['received_ratio'] = 100.0 * results[cid]['delivered'] / (results[cid]['sent'] or 1)
type='integer', multi='_get_statistics'
),
'scheduled': fields.function(
- _get_statistics, string='Total',
+ _get_statistics, string='Scheduled',
+ type='integer', multi='_get_statistics'
+ ),
+ 'failed': fields.function(
+ _get_statistics, string='Failed',
type='integer', multi='_get_statistics'
),
'sent': fields.function(
Statistics = self.pool['mail.mail.statistics']
results = dict.fromkeys(ids, False)
for mid in ids:
+ stat_ids = Statistics.search(cr, uid, [('mass_mailing_id', '=', mid)], context=context)
+ stats = Statistics.browse(cr, uid, stat_ids, context=context)
results[mid] = {
- 'total': Statistics.search(cr, uid, [('mass_mailing_id', '=', mid)], count=True, context=context),
- 'scheduled': Statistics.search(cr, uid, [('mass_mailing_id', '=', mid), ('scheduled', '!=', False), ('sent', '=', False)], count=True, context=context),
- 'sent': Statistics.search(cr, uid, [('mass_mailing_id', '=', mid), ('sent', '!=', False)], count=True, context=context),
- 'opened': Statistics.search(cr, uid, [('mass_mailing_id', '=', mid), ('opened', '!=', False)], count=True, context=context),
- 'replied': Statistics.search(cr, uid, [('mass_mailing_id', '=', mid), ('replied', '!=', False)], count=True, context=context),
- 'bounced': Statistics.search(cr, uid, [('mass_mailing_id', '=', mid), ('bounced', '!=', False)], count=True, context=context),
+ 'total': len(stats),
+ 'failed': len([s for s in stats if not s.scheduled is False and s.sent is False and not s.exception is False]),
+ 'scheduled': len([s for s in stats if not s.scheduled is False and s.sent is False]),
+ 'sent': len([s for s in stats if not s.sent is False]),
+ 'opened': len([s for s in stats if not s.opened is False]),
+ 'replied': len([s for s in stats if not s.replied is False]),
+ 'bounced': len([s for s in stats if not s.bounced is False]),
}
results[mid]['delivered'] = results[mid]['sent'] - results[mid]['bounced']
results[mid]['received_ratio'] = 100.0 * results[mid]['delivered'] / (results[mid]['sent'] or 1)
return res
def _get_private_models(self, context=None):
- return ['res.partner', 'mail.maass_mailing.contact']
+ 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)
_get_statistics, string='Scheduled',
type='integer', multi='_get_statistics',
),
+ 'failed': fields.function(
+ _get_statistics, string='Failed',
+ type='integer', multi='_get_statistics',
+ ),
'sent': fields.function(
_get_statistics, string='Sent',
type='integer', multi='_get_statistics',
# Bounce and tracking
'scheduled': fields.datetime('Scheduled', help='Date when the email has been created'),
'sent': fields.datetime('Sent', help='Date when the email has been sent'),
+ 'exception': fields.datetime('Exception', help='Date of technical error leading to the email not being sent'),
'opened': fields.datetime('Opened', help='Date when the email has been opened the first time'),
'replied': fields.datetime('Replied', help='Date when this email has been replied for the first time.'),
'bounced': fields.datetime('Bounced', help='Date when this email has bounced.'),
</group>
<group>
<field name="total" invisible="1"/>
- <div class="oe_right oe_button_box" name="buttons"
- attrs="{'invisible': [('total', '=', 0)]}">
- <button name="%(action_mail_mass_mailing_report)d"
- type="action" class="oe_stat_button oe_inline">
- <field name="received_ratio" widget="percentpie"/>
- <span>Received</span>
- </button>
- <button name="%(action_mail_mass_mailing_report)d"
- type="action" class="oe_stat_button oe_inline">
- <field name="opened_ratio" widget="percentpie"/>
- <span>Opened</span>
- </button>
- <button name="%(action_mail_mass_mailing_report)d"
- type="action" class="oe_stat_button oe_inline">
- <field name="replied_ratio" widget="percentpie"/>
- <span>Replied</span>
- </button>
-
- <button name="%(action_mail_mass_mailing_report)d"
- string="cacaprout"
- type="action" class="oe_stat_button oe_inline">
- <field name="opened_dayly" widget="barchart"/>
- <!-- <span>Opened Daily</span> -->
- </button>
- <!-- <p colspan="2">Here be some bar charts</p> -->
- <!-- <field name="opened_dayly" attrs="{'invisible': [('total', '=', 0)]}"/>
- <field name="replied_dayly" attrs="{'invisible': [('total', '=', 0)]}"/> -->
+ <div class="oe_right oe_button_box" name="buttons">
+ <div>
+ <button name="action_see_recipients" type="object"
+ icon="fa-user" class="oe_stat_button">
+ <field name="contact_nbr" string="Recipients" widget="statinfo"/>
+ </button>
+ <button name="%(action_mail_mass_mailing_report)d" type="action"
+ icon="fa-envelope-o" class="oe_stat_button">
+ <field name="total" string="Emails" widget="statinfo"/>
+ </button>
+ </div>
+ <div style="margin-top: 8px;"
+ attrs="{'invisible': [('total', '=', 0)]}">
+ <button name="%(action_mail_mass_mailing_report)d"
+ type="action" class="oe_stat_button">
+ <field name="received_ratio" string="Received" widget="percentpie"/>
+ </button>
+ <button name="%(action_mail_mass_mailing_report)d"
+ type="action" class="oe_stat_button">
+ <field name="opened_ratio" string="Opened" widget="percentpie"/>
+ </button>
+ <button name="%(action_mail_mass_mailing_report)d"
+ type="action" class="oe_stat_button">
+ <field name="replied_ratio" string="Replied" widget="percentpie"/>
+ </button>
+ </div>
+ <div style="margin-top: 8px;"
+ attrs="{'invisible': [('total', '=', 0)]}">
+ <button name="%(action_mail_mass_mailing_report)d"
+ type="action" class="oe_stat_button oe_inline">
+ <field name="opened_dayly" string="Opened Daily" widget="barchart"/>
+ </button>
+ <button name="%(action_mail_mass_mailing_report)d"
+ type="action" class="oe_stat_button oe_inline">
+ <field name="replied_dayly" string="Replied Daily" widget="barchart"/>
+ </button>
+ </div>
</div>
</group>
</group>
<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)]}"/> Replies go into the original document
- <span attrs="{'invisible': [('auto_reply_to_available', '=', True)]}"> (not available for those recipients)</span>
+ 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="mailing_model" widget="radio"
on_change='on_change_mailing_model(mailing_model, context)'/>
- <label for="contact_list_ids" string="Mailing Lists"/>
+ <label for="contact_list_ids" string="Mailing Lists" style="display: inline-block; min-width: 90px;"/>
<field name="contact_list_ids" widget="many2many_tags" options="{'no_create': True}"
class="oe_inline" placeholder="Choose mailing lists"
on_change="on_change_contact_list_ids(mailing_model, contact_list_ids, context)"/>
<span style="margin-left: 8px; margin-right: 8px">or</span>
<button string='Create a New List' class="oe_link" type='object' name='action_new_list'/><br />
- <label for="contact_nbr" string="Total"/>
- <field name="contact_nbr" nolabel="1" class="oe_inline" readonly="True"/> recipients
- <button name="action_see_recipients" type="object" string="See Recipients" class="oe_inline oe_link" style='margin-left: 8px;'/><br />
+ <!-- <label for="contact_nbr" string="Total" style="display: inline-block; min-width: 90px;"/> -->
+ <!-- <field name="contact_nbr" nolabel="1" class="oe_inline" readonly="True"/> recipients -->
+ <!-- <button name="action_see_recipients" type="object" string="See Recipients" class="oe_inline oe_link" style='margin-left: 8px;'/><br /> -->
<div groups="mass_mailing.group_mass_mailing_campaign" style="display: inline;">
<field name="ab_testing" invisible="1"/>
</div>
<field name="date" readonly="True" groups="mass_mailing.group_mass_mailing_campaign"/>
<field name="mass_mailing_campaign_id" groups="mass_mailing.group_mass_mailing_campaign"/>
- <label for="template_id"/>
- <div style="max-height: 200px; overflow: hidden !important;">
- <field name="template_id" string="Select Template" nolabel="1"
+ <label for="body_html" string="Email"/>
+ <div>
+ <label for="template_id" string="Template"/>
+ <field name="template_id" string="Select Template"
class="oe_inline" options="{'no_create': True, 'no_open': True}"
- on_change="on_change_template_id(template_id, context)"/>
+ on_change="on_change_template_id(template_id, context)"/><br />
<button name="action_edit_html" type="object" string="Edit Mail Content"
class="oe_link" style="margin-left: 8px"/>
<field name="body_html"/>