diff options
| author | Christophe Simonis <chs@odoo.com> | 2014-09-05 15:28:22 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2014-09-05 15:28:22 +0200 |
| commit | 31bf30d2d0eb78baaa36360b99fe58bf7cd4c9e7 (patch) | |
| tree | d7be61ecd6bb4c8b5552e39b03e2a64eebbbf323 /addons/mass_mailing/models | |
| parent | afba9e8817c458640ae446ac7aaaab79be4fe1e9 (diff) | |
| parent | ed1c173971968eaa96693cb4e1547efa6e6c34e0 (diff) | |
[MERGE] forward port of branch 8.0 up to ed1c173
Diffstat (limited to 'addons/mass_mailing/models')
| -rw-r--r-- | addons/mass_mailing/models/__init__.py | 1 | ||||
| -rw-r--r-- | addons/mass_mailing/models/mail_mail.py | 2 | ||||
| -rw-r--r-- | addons/mass_mailing/models/mail_thread.py | 8 | ||||
| -rw-r--r-- | addons/mass_mailing/models/mass_mailing.py | 13 | ||||
| -rw-r--r-- | addons/mass_mailing/models/mass_mailing_report.py | 52 | ||||
| -rw-r--r-- | addons/mass_mailing/models/mass_mailing_stats.py | 17 |
6 files changed, 82 insertions, 11 deletions
diff --git a/addons/mass_mailing/models/__init__.py b/addons/mass_mailing/models/__init__.py index 2cffe48642b..702da268d84 100644 --- a/addons/mass_mailing/models/__init__.py +++ b/addons/mass_mailing/models/__init__.py @@ -5,3 +5,4 @@ import mass_mailing_stats import mail_mail import mail_thread import res_config +import mass_mailing_report diff --git a/addons/mass_mailing/models/mail_mail.py b/addons/mass_mailing/models/mail_mail.py index 41be9c21cbf..03c7b155ad6 100644 --- a/addons/mass_mailing/models/mail_mail.py +++ b/addons/mass_mailing/models/mail_mail.py @@ -45,7 +45,7 @@ class MailMail(osv.Model): # TDE note: should be after 'all values computed', to have values (FIXME after merging other branch holding create refactoring) mail_id = super(MailMail, self).create(cr, uid, values, context=context) if values.get('statistics_ids'): - mail = self.browse(cr, SUPERUSER_ID, mail_id) + mail = self.browse(cr, SUPERUSER_ID, mail_id, context=context) for stat in mail.statistics_ids: self.pool['mail.mail.statistics'].write(cr, uid, [stat.id], {'message_id': mail.message_id}, context=context) return mail_id diff --git a/addons/mass_mailing/models/mail_thread.py b/addons/mass_mailing/models/mail_thread.py index 524341f88d7..7bfce705043 100644 --- a/addons/mass_mailing/models/mail_thread.py +++ b/addons/mass_mailing/models/mail_thread.py @@ -20,8 +20,8 @@ ############################################################################## import logging +import re -from openerp import tools from openerp.addons.mail.mail_message import decode from openerp.addons.mail.mail_thread import decode_header from openerp.osv import osv @@ -46,7 +46,11 @@ class MailThread(osv.AbstractModel): # 0. Verify whether this is a bounced email (wrong destination,...) -> use it to collect data, such as dead leads if bounce_alias in email_to: - bounce_match = tools.bounce_re.search(email_to) + # Bounce regex + # Typical form of bounce is bounce_alias-128-crm.lead-34@domain + # group(1) = the mail ID; group(2) = the model (if any); group(3) = the record ID + bounce_re = re.compile("%s-(\d+)-?([\w.]+)?-?(\d+)?" % re.escape(bounce_alias), re.UNICODE) + bounce_match = bounce_re.search(email_to) if bounce_match: bounced_model, bounced_thread_id = None, False bounced_mail_id = bounce_match.group(1) diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py index ae1a334f698..bee3e8528f9 100644 --- a/addons/mass_mailing/models/mass_mailing.py +++ b/addons/mass_mailing/models/mass_mailing.py @@ -9,6 +9,7 @@ from openerp import tools from openerp.exceptions import Warning from openerp.tools.safe_eval import safe_eval as eval from openerp.tools.translate import _ +from openerp.tools import ustr from openerp.osv import osv, fields @@ -29,6 +30,7 @@ class MassMailingContact(osv.Model): be able to deal with large contact list to email without bloating the partner base.""" _name = 'mail.mass_mailing.contact' + _inherit = 'mail.thread' _description = 'Mass Mailing Contact' _order = 'email' _rec_name = 'email' @@ -271,7 +273,7 @@ class MassMailing(osv.Model): """ date_begin = date_begin.date() section_result = [{'value': 0, - 'tooltip': (date_begin + relativedelta.relativedelta(days=i)).strftime('%d %B %Y'), + 'tooltip': ustr((date_begin + relativedelta.relativedelta(days=i)).strftime('%d %B %Y')), } for i in range(0, self._period_number)] group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context) field_col_info = obj._all_columns.get(groupby_field.split(':')[0]) @@ -302,7 +304,7 @@ class MassMailing(osv.Model): return res def _get_statistics(self, cr, uid, ids, name, arg, context=None): - """ Compute statistics of the mass mailing campaign """ + """ Compute statistics of the mass mailing """ results = {} cr.execute(""" SELECT @@ -311,9 +313,9 @@ class MassMailing(osv.Model): COUNT(CASE WHEN s.sent is not null THEN 1 ELSE null END) AS sent, COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is null THEN 1 ELSE null END) AS scheduled, COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is not null THEN 1 ELSE null END) AS failed, - COUNT(CASE WHEN s.id is not null AND s.bounced is null THEN 1 ELSE null END) AS delivered, + COUNT(CASE WHEN s.sent is not null AND s.bounced is null THEN 1 ELSE null END) AS delivered, COUNT(CASE WHEN s.opened is not null THEN 1 ELSE null END) AS opened, - COUNT(CASE WHEN s.replied is not null THEN 1 ELSE null END) AS replied , + COUNT(CASE WHEN s.replied is not null THEN 1 ELSE null END) AS replied, COUNT(CASE WHEN s.bounced is not null THEN 1 ELSE null END) AS bounced FROM mail_mail_statistics s @@ -328,7 +330,6 @@ class MassMailing(osv.Model): for row in cr.dictfetchall(): results[row.pop('mailing_id')] = row total = row['total'] or 1 - row['delivered'] = row['sent'] - row['bounced'] row['received_ratio'] = 100.0 * row['delivered'] / total row['opened_ratio'] = 100.0 * row['opened'] / total row['replied_ratio'] = 100.0 * row['replied'] / total @@ -601,7 +602,7 @@ class MassMailing(osv.Model): 'composition_mode': 'mass_mail', 'mass_mailing_id': mailing.id, 'mailing_list_ids': [(4, l.id) for l in mailing.contact_list_ids], - 'same_thread': mailing.reply_to_mode == 'thread', + 'no_auto_thread': mailing.reply_to_mode != 'thread', } if mailing.reply_to_mode == 'email': composer_values['reply_to'] = mailing.reply_to diff --git a/addons/mass_mailing/models/mass_mailing_report.py b/addons/mass_mailing/models/mass_mailing_report.py new file mode 100644 index 00000000000..9d91be2759f --- /dev/null +++ b/addons/mass_mailing/models/mass_mailing_report.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import fields, osv +from openerp import tools + + +class MassMailingReport(osv.Model): + _name = 'mail.statistics.report' + _auto = False + _description = 'Mass Mailing Statistics' + + _columns = { + 'scheduled_date': fields.datetime('Scheduled Date', readonly=True), + 'name': fields.char('Mass Mail', readonly=True), + 'campaign': fields.char('Mass Mail Campaign', readonly=True), + 'sent': fields.integer('Sent', readonly=True), + 'delivered': fields.integer('Delivered', readonly=True), + 'opened': fields.integer('Opened', readonly=True), + 'bounced': fields.integer('Bounced', readonly=True), + 'replied': fields.integer('Replied', readonly=True), + 'state': fields.selection( + [('draft', 'Draft'), ('test', 'Tested'), ('done', 'Sent')], + string='Status', readonly=True, + ), + 'email_from': fields.char('From', readonly=True), + } + + def init(self, cr): + """Mass Mail Statistical Report: based on mail.mail.statistics that models the various + statistics collected for each mailing, and mail.mass_mailing model that models the + various mailing performed. """ + tools.drop_view_if_exists(cr, 'mail_statistics_report') + cr.execute(""" + CREATE OR REPLACE VIEW mail_statistics_report AS ( + SELECT + min(ms.id) as id, + ms.scheduled as scheduled_date, + mm.name as name, + mc.name as campaign, + count(ms.bounced) as bounced, + count(ms.sent) as sent, + (count(ms.sent) - count(ms.bounced)) as delivered, + count(ms.opened) as opened, + count(ms.replied) as replied, + mm.state, + mm.email_from + FROM + mail_mail_statistics as ms + left join mail_mass_mailing as mm ON (ms.mass_mailing_id=mm.id) + left join mail_mass_mailing_campaign as mc ON (ms.mass_mailing_campaign_id=mc.id) + GROUP BY ms.scheduled, mm.name, mc.name, mm.state, mm.email_from + )""") diff --git a/addons/mass_mailing/models/mass_mailing_stats.py b/addons/mass_mailing/models/mass_mailing_stats.py index 7e8c194f42e..c3cd4314fa6 100644 --- a/addons/mass_mailing/models/mass_mailing_stats.py +++ b/addons/mass_mailing/models/mass_mailing_stats.py @@ -21,6 +21,7 @@ from openerp.osv import osv, fields + class MailMailStats(osv.Model): """ MailMailStats models the statistics collected about emails. Those statistics are stored in a separated model and table to avoid bloating the mail_mail table @@ -33,7 +34,13 @@ class MailMailStats(osv.Model): _order = 'message_id' _columns = { - 'mail_mail_id': fields.many2one('mail.mail', 'Mail ID', ondelete='set null'), + 'mail_mail_id': fields.many2one('mail.mail', 'Mail', ondelete='set null'), + 'mail_mail_id_int': fields.integer( + 'Mail ID (tech)', + help='ID of the related mail_mail. This field is an integer field because' + 'the related mail_mail can be deleted separately from its statistics.' + 'However the ID is needed for several action and controllers.' + ), 'message_id': fields.char('Message-ID'), 'model': fields.char('Document model'), 'res_id': fields.integer('Document ID'), @@ -62,9 +69,15 @@ class MailMailStats(osv.Model): 'scheduled': fields.datetime.now, } + def create(self, cr, uid, values, context=None): + if 'mail_mail_id' in values: + values['mail_mail_id_int'] = values['mail_mail_id'] + res = super(MailMailStats, self).create(cr, uid, values, context=context) + return res + def _get_ids(self, cr, uid, ids=None, mail_mail_ids=None, mail_message_ids=None, domain=None, context=None): if not ids and mail_mail_ids: - base_domain = [('mail_mail_id', 'in', mail_mail_ids)] + base_domain = [('mail_mail_id_int', 'in', mail_mail_ids)] elif not ids and mail_message_ids: base_domain = [('message_id', 'in', mail_message_ids)] else: |
