diff --git a/mail_tracking/__manifest__.py b/mail_tracking/__manifest__.py
index 5914214..f088398 100644
--- a/mail_tracking/__manifest__.py
+++ b/mail_tracking/__manifest__.py
@@ -7,14 +7,14 @@
{
"name": "Email tracking",
"summary": "Email tracking system for all mails sent",
- "version": "12.0.2.0.1",
+ "version": "13.0.1.0.0",
"category": "Social Network",
"website": "http://github.com/OCA/social",
"author": ("Tecnativa, " "Odoo Community Association (OCA)"),
"license": "AGPL-3",
"application": False,
"installable": True,
- "depends": ["decimal_precision", "mail"],
+ "depends": ["mail"],
"data": [
"data/tracking_data.xml",
"security/mail_tracking_email_security.xml",
diff --git a/mail_tracking/hooks.py b/mail_tracking/hooks.py
index 5693ebc..6605482 100644
--- a/mail_tracking/hooks.py
+++ b/mail_tracking/hooks.py
@@ -5,20 +5,11 @@ import logging
from psycopg2.extensions import AsIs
+from odoo.tools import column_exists
+
_logger = logging.getLogger(__name__)
-def column_exists(cr, table, column):
- cr.execute(
- """
- SELECT column_name
- FROM information_schema.columns
- WHERE table_name = %s AND column_name = %s""",
- (table, column),
- )
- return bool(cr.fetchall())
-
-
def column_add_with_value(cr, table, column, field_type, value):
if not column_exists(cr, table, column):
cr.execute(
diff --git a/mail_tracking/migrations/12.0.2.0.0/post-migrate.py b/mail_tracking/migrations/12.0.2.0.0/post-migrate.py
deleted file mode 100644
index 6b2993c..0000000
--- a/mail_tracking/migrations/12.0.2.0.0/post-migrate.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2019 Alexandre Díaz
-# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
-
-
-from openupgradelib.openupgrade import migrate
-
-
-@migrate()
-def migrate(env, version):
- cr = env.cr
- cr.execute("UPDATE mail_tracking_email SET token = NULL")
diff --git a/mail_tracking/models/mail_bounced_mixin.py b/mail_tracking/models/mail_bounced_mixin.py
index d63b445..488831a 100644
--- a/mail_tracking/models/mail_bounced_mixin.py
+++ b/mail_tracking/models/mail_bounced_mixin.py
@@ -12,11 +12,10 @@ class MailBouncedMixin(models.AbstractModel):
_name = "mail.bounced.mixin"
_description = "Mail bounced mixin"
- _primary_email = ["email"]
+ _primary_email = "email"
email_bounced = fields.Boolean(index=True)
- @api.multi
def email_bounced_set(self, tracking_emails, reason, event=None):
"""Inherit this method to make any other actions to the model that
inherit the mixin"""
@@ -28,7 +27,7 @@ class MailBouncedMixin(models.AbstractModel):
return partners.write({"email_bounced": True})
def write(self, vals):
- [email_field] = self._primary_email
+ email_field = self._primary_email
if email_field not in vals:
return super().write(vals)
email = vals[email_field].lower() if vals[email_field] else False
diff --git a/mail_tracking/models/mail_message.py b/mail_tracking/models/mail_message.py
index f709c33..c0c818a 100644
--- a/mail_tracking/models/mail_message.py
+++ b/mail_tracking/models/mail_message.py
@@ -132,8 +132,8 @@ class MailMessage(models.Model):
# Search all recipients for this message
if message.partner_ids:
partners |= message.partner_ids
- if message.needaction_partner_ids:
- partners |= message.needaction_partner_ids
+ if message.notified_partner_ids:
+ partners |= message.notified_partner_ids
# Remove recipients already included
partners -= partners_already
tracking_unkown_values = {
@@ -179,7 +179,6 @@ class MailMessage(models.Model):
message_dict.update(tracking_statuses[mail_message_id])
return res
- @api.multi
def _prepare_dict_failed_message(self):
"""Preare values to be used by the chatter widget"""
self.ensure_one()
@@ -200,7 +199,6 @@ class MailMessage(models.Model):
"failed_recipients": failed_recipients,
}
- @api.multi
def get_failed_messages(self):
"""Returns the list of failed messages to be used by the
failed_messages widget"""
@@ -209,7 +207,6 @@ class MailMessage(models.Model):
for msg in self.sorted("date", reverse=True)
]
- @api.multi
def set_need_action_done(self):
"""Set message tracking action as done
diff --git a/mail_tracking/models/mail_resend_message.py b/mail_tracking/models/mail_resend_message.py
index 1ba8c19..4c7dad2 100644
--- a/mail_tracking/models/mail_resend_message.py
+++ b/mail_tracking/models/mail_resend_message.py
@@ -36,7 +36,6 @@ class MailResendMessage(models.TransientModel):
rec["partner_ids"].extend(partner_ids)
return rec
- @api.multi
def resend_mail_action(self):
for wizard in self:
to_send = wizard.partner_ids.filtered("resend").mapped("partner_id")
diff --git a/mail_tracking/models/mail_thread.py b/mail_tracking/models/mail_thread.py
index 3f6525f..3682ea3 100644
--- a/mail_tracking/models/mail_thread.py
+++ b/mail_tracking/models/mail_thread.py
@@ -29,7 +29,6 @@ class MailThread(models.AbstractModel):
("mail_tracking_ids.state", "in", list(failed_states)),
]
- @api.multi
@api.returns("self", lambda value: value.id)
def message_post(self, *args, **kwargs):
"""Adds CC recipient to the message.
@@ -43,13 +42,12 @@ class MailThread(models.AbstractModel):
new_message.sudo().write({"email_cc": email_cc})
return new_message
- @api.multi
- def message_get_suggested_recipients(self):
+ def _message_get_suggested_recipients(self):
"""Adds email Cc recipients as suggested recipients.
If the recipient has a res.partner, use it.
"""
- res = super().message_get_suggested_recipients()
+ res = super()._message_get_suggested_recipients()
ResPartnerObj = self.env["res.partner"]
email_cc_formated_list = []
for record in self:
@@ -65,7 +63,7 @@ class MailThread(models.AbstractModel):
if not partner_id:
record._message_add_suggested_recipient(res, email=cc, reason=_("Cc"))
else:
- partner = ResPartnerObj.browse(partner_id, self._prefetch)
+ partner = ResPartnerObj.browse(partner_id)
record._message_add_suggested_recipient(
res, partner=partner, reason=_("Cc")
)
diff --git a/mail_tracking/models/mail_tracking_email.py b/mail_tracking/models/mail_tracking_email.py
index 37eda13..aa7e1c2 100644
--- a/mail_tracking/models/mail_tracking_email.py
+++ b/mail_tracking/models/mail_tracking_email.py
@@ -8,8 +8,7 @@ import urllib.parse
import uuid
from datetime import datetime
-from odoo import models, api, fields, tools
-import odoo.addons.decimal_precision as dp
+from odoo import api, fields, models, tools
_logger = logging.getLogger(__name__)
@@ -36,8 +35,8 @@ class MailTrackingEmail(models.Model):
compute="_compute_tracking_display_name",
)
timestamp = fields.Float(
- string='UTC timestamp', readonly=True,
- digits=dp.get_precision('MailTracking Timestamp'))
+ string="UTC timestamp", readonly=True, digits="MailTracking Timestamp"
+ )
time = fields.Datetime(string="Time", readonly=True, index=True)
date = fields.Date(
string="Date", readonly=True, compute="_compute_date", store=True
@@ -125,7 +124,6 @@ class MailTrackingEmail(models.Model):
).write({"mail_tracking_needs_action": True})
return records
- @api.multi
def write(self, vals):
super().write(vals)
state = vals.get("state")
@@ -255,7 +253,6 @@ class MailTrackingEmail(models.Model):
% {"url": track_url, "tracking_email_id": self.id}
)
- @api.multi
def _partners_email_bounced_set(self, reason, event=None):
recipients = []
if event and event.recipient_address:
@@ -267,7 +264,6 @@ class MailTrackingEmail(models.Model):
[("email", "=ilike", recipient)]
).email_bounced_set(self, reason, event=event)
- @api.multi
def smtp_error(self, mail_server, smtp_server, exception):
values = {"state": "error"}
IrMailServer = self.env["ir.mail_server"]
@@ -292,7 +288,6 @@ class MailTrackingEmail(models.Model):
self.sudo()._partners_email_bounced_set("error")
self.sudo().write(values)
- @api.multi
def tracking_img_add(self, email):
self.ensure_one()
tracking_url = self._get_mail_tracking_img()
@@ -311,20 +306,18 @@ class MailTrackingEmail(models.Model):
if not self.mail_message_id.exists(): # pragma: no cover
return True
mail_message = self.mail_message_id
- partners = (
- mail_message.needaction_partner_ids | mail_message.partner_ids)
- if (self.partner_id and self.partner_id not in partners):
+ partners = mail_message.notified_partner_ids | mail_message.partner_ids
+ if self.partner_id and self.partner_id not in partners:
# If mail_message haven't tracking partner, then
# add it in order to see his tracking status in chatter
if mail_message.subtype_id:
- mail_message.sudo().write({
- 'needaction_partner_ids': [(4, self.partner_id.id)],
- })
+ mail_message.sudo().write(
+ {"notified_partner_ids": [(4, self.partner_id.id)]}
+ )
else:
mail_message.sudo().write({"partner_ids": [(4, self.partner_id.id)]})
return True
- @api.multi
def _tracking_sent_prepare(self, mail_server, smtp_server, message, message_id):
self.ensure_one()
ts = time.time()
@@ -368,7 +361,6 @@ class MailTrackingEmail(models.Model):
concurrent_event_ids = m_event.search(domain)
return concurrent_event_ids
- @api.multi
def event_create(self, event_type, metadata):
event_ids = self.env["mail.tracking.event"]
for tracking_email in self:
diff --git a/mail_tracking/models/mail_tracking_event.py b/mail_tracking/models/mail_tracking_event.py
index b7f91df..e6af3e1 100644
--- a/mail_tracking/models/mail_tracking_event.py
+++ b/mail_tracking/models/mail_tracking_event.py
@@ -5,8 +5,7 @@ import re
import time
from datetime import datetime
-from odoo import models, api, fields
-import odoo.addons.decimal_precision as dp
+from odoo import api, fields, models
class MailTrackingEvent(models.Model):
@@ -24,8 +23,8 @@ class MailTrackingEvent(models.Model):
index=True,
)
timestamp = fields.Float(
- string='UTC timestamp', readonly=True,
- digits=dp.get_precision('MailTracking Timestamp'))
+ string="UTC timestamp", readonly=True, digits="MailTracking Timestamp"
+ )
time = fields.Datetime(string="Time", readonly=True)
date = fields.Date(
string="Date", readonly=True, compute="_compute_date", store=True
@@ -81,7 +80,6 @@ class MailTrackingEvent(models.Model):
else:
email.recipient_address = False
- @api.multi
@api.depends("time")
def _compute_date(self):
for email in self:
diff --git a/mail_tracking/models/res_partner.py b/mail_tracking/models/res_partner.py
index 9a72af8..1133a79 100644
--- a/mail_tracking/models/res_partner.py
+++ b/mail_tracking/models/res_partner.py
@@ -11,23 +11,20 @@ class ResPartner(models.Model):
# tracking_emails_count and email_score are non-store fields in order
# to improve performance
tracking_emails_count = fields.Integer(
- compute="_compute_tracking_emails_count", readonly=True
+ compute="_compute_email_score_and_count", readonly=True
)
- email_score = fields.Float(compute="_compute_email_score", readonly=True)
+ email_score = fields.Float(compute="_compute_email_score_and_count", readonly=True)
@api.depends("email")
- def _compute_email_score(self):
- for partner in self.filtered('email'):
- partner.email_score = self.env['mail.tracking.email'].\
- email_score_from_email(partner.email)
-
- @api.multi
- @api.depends('email')
- def _compute_tracking_emails_count(self):
- for partner in self:
- count = 0
- if partner.email:
- count = self.env["mail.tracking.email"].search_count(
- [("recipient_address", "=", partner.email.lower())]
- )
- partner.tracking_emails_count = count
+ def _compute_email_score_and_count(self):
+ partners_mail = self.filtered("email")
+ mail_tracking_obj = self.env["mail.tracking.email"]
+ for partner in partners_mail:
+ partner.email_score = self.env[
+ "mail.tracking.email"
+ ].email_score_from_email(partner.email)
+ partner.tracking_emails_count = mail_tracking_obj.search_count(
+ [("recipient_address", "=", partner.email.lower())]
+ )
+ partners_no_mail = self - partners_mail
+ partners_no_mail.update({"email_score": 50.0, "tracking_emails_count": 0})
diff --git a/mail_tracking/static/src/js/failed_message/discuss.js b/mail_tracking/static/src/js/failed_message/discuss.js
index 847443d..6deb131 100644
--- a/mail_tracking/static/src/js/failed_message/discuss.js
+++ b/mail_tracking/static/src/js/failed_message/discuss.js
@@ -169,9 +169,9 @@ odoo.define('mail_tracking.FailedMessageDiscuss', function (require) {
/**
* Render 'failed' mailbox menu entry in Discuss
+ * - Initial render
*
- * @private
- * @returns {jQueryElementt}
+ * @override
*/
_renderSidebar: function () {
var $sidebar = this._super.apply(this, arguments);
@@ -184,6 +184,19 @@ odoo.define('mail_tracking.FailedMessageDiscuss', function (require) {
return $sidebar;
},
+ /**
+ * Render 'failed' mailbox menu entry in Discuss
+ * - Update status render (not called if the mailbox is empty)
+ *
+ * @override
+ */
+ _renderSidebarMailboxes: function () {
+ this._super.apply(this, arguments);
+ this.$('.o_mail_discuss_sidebar_mailboxes').append(
+ QWeb.render('mail_tracking.SidebarFailed',
+ this._sidebarQWebParams()));
+ },
+
/**
* Overrides to listen click on 'Set all as reviewed' button
*
diff --git a/mail_tracking/static/src/xml/failed_message/discuss.xml b/mail_tracking/static/src/xml/failed_message/discuss.xml
index 45fb1f5..8f56388 100644
--- a/mail_tracking/static/src/xml/failed_message/discuss.xml
+++ b/mail_tracking/static/src/xml/failed_message/discuss.xml
@@ -8,13 +8,13 @@
This is a test message
', - }) - message._notify(message, {}, force_send=True) + message = self.env["mail.message"].create( + { + "subject": "Message test", + "author_id": self.sender.id, + "email_from": self.sender.email, + "message_type": "comment", + "model": "res.partner", + "res_id": self.recipient.id, + "partner_ids": [(4, self.recipient.id)], + "body": "This is a test message
", + } + ) + message._moderate_accept() # Search tracking created tracking_email = self.env["mail.tracking.email"].search( [ @@ -102,7 +104,7 @@ class TestMailTracking(TransactionCase): message_dict = message.message_format()[0] self.assertTrue(len(message_dict["partner_ids"]) > 0) # First partner is recipient - partner_id = message_dict["partner_ids"][0][0] + partner_id = message_dict["partner_ids"][0] self.assertEqual(partner_id, self.recipient.id) status = message_dict["partner_trackings"][0] # Tracking status must be sent and @@ -137,7 +139,7 @@ class TestMailTracking(TransactionCase): "body": "This is a test message
", } ) - message._notify(message, {}, force_send=True) + message._moderate_accept() # Search tracking created tracking_email = self.env["mail.tracking.email"].search( [ @@ -201,7 +203,7 @@ class TestMailTracking(TransactionCase): "body": "This is another test message
", } ) - message._notify(message, {}, force_send=True) + message._moderate_accept() recipients = self.recipient._message_get_suggested_recipients() self.assertEqual(len(recipients[self.recipient.id][0]), 3) self._check_partner_trackings(message) @@ -233,6 +235,45 @@ class TestMailTracking(TransactionCase): values = tracking.mail_message_id.get_failed_messages()[0] self.assertEqual(values["author"][0], -1) + def test_resend_failed_message(self): + # This message will generate a notification for recipient + message = self.env["mail.message"].create( + { + "subject": "Message test", + "author_id": self.sender.id, + "email_from": self.sender.email, + "message_type": "comment", + "model": "res.partner", + "res_id": self.recipient.id, + "partner_ids": [(4, self.recipient.id)], + "body": "This is a test message
", + } + ) + message._moderate_accept() + # Search tracking created + tracking_email = self.env["mail.tracking.email"].search( + [ + ("mail_message_id", "=", message.id), + ("partner_id", "=", self.recipient.id), + ] + ) + # Force error state + tracking_email.state = "error" + # Create resend mail wizard + wizard = ( + self.env["mail.resend.message"] + .sudo() + .with_context({"mail_message_to_resend": message.id}) + .create({}) + ) + # Check failed recipient)s + self.assertTrue(any(wizard.partner_ids)) + self.assertEqual(self.recipient.email, wizard.partner_ids[0].email) + # Resend message + wizard.resend_mail_action() + # Check tracking reset + self.assertFalse(tracking_email.state) + def mail_send(self, recipient): mail = self.env["mail.mail"].create( { diff --git a/mail_tracking/views/mail_tracking_email_view.xml b/mail_tracking/views/mail_tracking_email_view.xml index fc97c76..57a28b3 100644 --- a/mail_tracking/views/mail_tracking_email_view.xml +++ b/mail_tracking/views/mail_tracking_email_view.xml @@ -42,7 +42,10 @@