summaryrefslogtreecommitdiff
path: root/addons/mass_mailing/models
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2014-09-05 15:28:22 +0200
committerChristophe Simonis <chs@odoo.com>2014-09-05 15:28:22 +0200
commit31bf30d2d0eb78baaa36360b99fe58bf7cd4c9e7 (patch)
treed7be61ecd6bb4c8b5552e39b03e2a64eebbbf323 /addons/mass_mailing/models
parentafba9e8817c458640ae446ac7aaaab79be4fe1e9 (diff)
parented1c173971968eaa96693cb4e1547efa6e6c34e0 (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__.py1
-rw-r--r--addons/mass_mailing/models/mail_mail.py2
-rw-r--r--addons/mass_mailing/models/mail_thread.py8
-rw-r--r--addons/mass_mailing/models/mass_mailing.py13
-rw-r--r--addons/mass_mailing/models/mass_mailing_report.py52
-rw-r--r--addons/mass_mailing/models/mass_mailing_stats.py17
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: