Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions mail_tracking/README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

==============
Email tracking
==============
Expand All @@ -17,7 +13,7 @@ Email tracking
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmail-lightgray.png?logo=github
Expand Down Expand Up @@ -175,6 +171,10 @@ Contributors

- Tris Doan

- `Onestein <https://onestein.nl>`__:

- Dennis Sluijk

Other credits
-------------

Expand Down
35 changes: 34 additions & 1 deletion mail_tracking/models/res_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,40 @@ class ResPartner(models.Model):
tracking_emails_count = fields.Integer(
compute="_compute_email_score_and_count", readonly=True
)
email_score = fields.Float(compute="_compute_email_score_and_count", readonly=True)
email_score = fields.Float(
compute="_compute_email_score_and_count",
search="_search_email_score",
readonly=True,
)

def _search_email_score(self, operator, value):
supported_operators = ["<", ">", "<=", ">=", "=", "!="]
if operator not in supported_operators:
raise NotImplementedError()

weights = self.env["mail.tracking.email"]._email_score_weights()
case_expr = " ".join(
f"WHEN '{state}' THEN {score}" for state, score in weights.items()
)
state_expr = f"CASE state {case_expr} ELSE 0.0 END"

query = f"""
SELECT partner.id
FROM res_partner partner
LEFT JOIN (
SELECT recipient_address,
GREATEST(0.0, LEAST(100.0,
50.0 + SUM({state_expr})
)) AS score
FROM mail_tracking_email
WHERE recipient_address IS NOT NULL
GROUP BY recipient_address
) mte ON mte.recipient_address = LOWER(partner.email)
WHERE COALESCE(mte.score, 50.0) {operator} %s
"""
self.env.cr.execute(query, (value,))
partner_ids = [row[0] for row in self.env.cr.fetchall()]
return [("id", "in", partner_ids)]

@api.depends("email")
def _compute_email_score_and_count(self):
Expand Down
2 changes: 2 additions & 0 deletions mail_tracking/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@
- Agustín Payen Sandoval
- [Trobz](https://www.trobz.com):
- Tris Doan
- [Onestein](https://onestein.nl):
- Dennis Sluijk
38 changes: 18 additions & 20 deletions mail_tracking/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>Email tracking</title>
<style type="text/css">

/*
Expand Down Expand Up @@ -360,21 +360,16 @@
</style>
</head>
<body>
<div class="document">
<div class="document" id="email-tracking">
<h1 class="title">Email tracking</h1>


<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="email-tracking">
<h1>Email tracking</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:902f0a30b6020fdbda685a7f257611036b54042daab360ce03b167dad7d98717
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/mail/tree/18.0/mail_tracking"><img alt="OCA/mail" src="https://img.shields.io/badge/github-OCA%2Fmail-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_tracking"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/mail&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/mail/tree/18.0/mail_tracking"><img alt="OCA/mail" src="https://img.shields.io/badge/github-OCA%2Fmail-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/mail-18-0/mail-18-0-mail_tracking"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/mail&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module shows email notification tracking status for any messages in
mail thread (chatter). Each notified partner will have an intuitive icon
just right to his name.</p>
Expand All @@ -396,23 +391,23 @@ <h1>Email tracking</h1>
</ul>
</div>
<div class="section" id="installation">
<h2><a class="toc-backref" href="#toc-entry-1">Installation</a></h2>
<h1><a class="toc-backref" href="#toc-entry-1">Installation</a></h1>
<p>If you’re using a multi-database installation (with or without dbfilter
option) where /web/databse/selector returns a list of more than one
database, then you need to add <tt class="docutils literal">mail_tracking</tt> addon to wide load
addons list (by default, only <tt class="docutils literal">web</tt> addon), setting <tt class="docutils literal"><span class="pre">--load</span></tt> option.
For example, <tt class="docutils literal"><span class="pre">--load=web,mail,mail_tracking</span></tt></p>
</div>
<div class="section" id="configuration">
<h2><a class="toc-backref" href="#toc-entry-2">Configuration</a></h2>
<h1><a class="toc-backref" href="#toc-entry-2">Configuration</a></h1>
<p>As there can be scenarios where sending a tracking img in the email body
is not desired, there is a global system parameter
“mail_tracking.tracking_img_disabled” that can be set to True to remove
the tracking img from all outgoing emails. Note that the <strong>Opened</strong>
status will not be available in this case.</p>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-3">Usage</a></h2>
<h1><a class="toc-backref" href="#toc-entry-3">Usage</a></h1>
<p>When user sends a message in mail_thread (chatter), for instance in
partner form, then an email tracking is created for each email
notification. Then a status icon will appear just right to name of
Expand Down Expand Up @@ -454,31 +449,31 @@ <h2><a class="toc-backref" href="#toc-entry-3">Usage</a></h2>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h2><a class="toc-backref" href="#toc-entry-4">Known issues / Roadmap</a></h2>
<h1><a class="toc-backref" href="#toc-entry-4">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Integrate with the core <tt class="docutils literal">mail.notification</tt> model as it overlaps
with what the <tt class="docutils literal">mail.tracking</tt> model does. We could add the existing
features on top of that model and save lots of code lines.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h2>
<h1><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/mail/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/mail/issues/new?body=module:%20mail_tracking%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-6">Credits</a></h2>
<h1><a class="toc-backref" href="#toc-entry-6">Credits</a></h1>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-7">Authors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-7">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-8">Contributors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
Expand All @@ -501,15 +496,19 @@ <h3><a class="toc-backref" href="#toc-entry-8">Contributors</a></h3>
<li>Tris Doan</li>
</ul>
</li>
<li><a class="reference external" href="https://onestein.nl">Onestein</a>:<ul>
<li>Dennis Sluijk</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="other-credits">
<h3><a class="toc-backref" href="#toc-entry-9">Other credits</a></h3>
<h2><a class="toc-backref" href="#toc-entry-9">Other credits</a></h2>
<p>The migration of this module from 17.0 to 18.0 was financially supported
by Camptocamp.</p>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h3>
<h2><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
Expand All @@ -522,6 +521,5 @@ <h3><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h3>
</div>
</div>
</div>
</div>
</body>
</html>
64 changes: 64 additions & 0 deletions mail_tracking/tests/test_mail_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ def setUp(self, *args, **kwargs):
self.recipient = self.env["res.partner"].create(
{"name": "Test recipient", "email": "recipient@example.com"}
)
self.recipient_1 = self.env["res.partner"].create(
{"name": "Test recipient 1", "email": "recipient1@example.com"}
)
self.recipient_2 = self.env["res.partner"].create(
{"name": "Test recipient 2", "email": "recipient2@example.com"}
)
self.recipients = self.recipient + self.recipient_1 + self.recipient_2
self.last_request = http.request
http.request = type(
"obj",
Expand Down Expand Up @@ -778,6 +785,63 @@ def test_search_is_failed_message(self):
)
)

def test_search_on_email_score(self):
recipients_domain = [("id", "in", self.recipients.ids)]
mail, tracking = self.mail_send(self.recipient.email)
tracking.event_create("open", {})
mail, tracking = self.mail_send(self.recipient.email)
tracking.event_create("open", {})

mail, tracking = self.mail_send(self.recipient_1.email)
tracking.event_create("reject", {})

# Ensure the email_score is correctly computed for the 3 partners of the test
self.assertEqual(60.0, self.recipient.email_score)
self.assertEqual(25.0, self.recipient_1.email_score)
self.assertEqual(50.0, self.recipient_2.email_score)

# Search for email_score > 50
result = self.env["res.partner"].search(
recipients_domain + [("email_score", ">", 50)]
)
self.assertEqual(result, self.recipient)

# Search for email_score < 30
result = self.env["res.partner"].search(
recipients_domain + [("email_score", "<", 30)]
)
self.assertEqual(result, self.recipient_1)

# Search for email_score = 50
result = self.env["res.partner"].search(
recipients_domain + [("email_score", "=", 50)]
)
self.assertEqual(result, self.recipient_2)

# Search for email_score >= 50
result = self.env["res.partner"].search(
recipients_domain + [("email_score", ">=", 50)]
)
self.assertEqual(result, self.recipient + self.recipient_2)

# Search for email_score <= 50
result = self.env["res.partner"].search(
recipients_domain + [("email_score", "<=", 50)]
)
self.assertEqual(result, self.recipient_1 + self.recipient_2)

# Search for email_score != 50
result = self.env["res.partner"].search(
recipients_domain + [("email_score", "!=", 50)]
)
self.assertEqual(result, self.recipient + self.recipient_1)

# Search for email_score between 30 and 65
result = self.env["res.partner"].search(
recipients_domain + [("email_score", ">", 30), ("email_score", "<", 65)]
)
self.assertEqual(result, self.recipient + self.recipient_2)


@tagged("-at_install", "post_install")
class TestAccessTrackingEmail(HttpCaseWithUserDemo, TestMailTracking):
Expand Down
Loading