forked from OCA/social
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d471fe3
commit 676bc43
Showing
23 changed files
with
466 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
"name": "Mail Autosubscribe", | ||
"summary": "Automatically subscribe partners to its company's business documents", | ||
"version": "14.0.1.0.0", | ||
"author": "Camptocamp SA, Odoo Community Association (OCA)", | ||
"license": "AGPL-3", | ||
"category": "Marketing", | ||
"depends": ["mail"], | ||
"website": "https://github.com/OCA/social", | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"views/mail_autosubscribe.xml", | ||
"views/mail_template.xml", | ||
"views/res_partner.xml", | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from . import models | ||
from . import res_partner | ||
from . import mail_thread | ||
from . import mail_autosubscribe | ||
from . import mail_template |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import api, fields, models | ||
|
||
|
||
class MailAutosubscribe(models.Model): | ||
_name = "mail.autosubscribe" | ||
_description = "Mail Autosubscribe" | ||
|
||
_sql_constraints = [ | ||
( | ||
"model_id_unique", | ||
"UNIQUE(model_id)", | ||
"There's already a rule for this model", | ||
) | ||
] | ||
|
||
model_id = fields.Many2one( | ||
"ir.model", | ||
required=True, | ||
index=True, | ||
ondelete="cascade", | ||
) | ||
model = fields.Char( | ||
related="model_id.model", | ||
string="Model Name", | ||
store=True, | ||
index=True, | ||
) | ||
name = fields.Char( | ||
compute="_compute_name", | ||
store=True, | ||
readonly=False, | ||
) | ||
|
||
@api.depends("model_id") | ||
def _compute_name(self): | ||
for rec in self: | ||
if not rec.name: | ||
rec.name = rec.model_id.name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import fields, models | ||
|
||
|
||
class MailTemplate(models.Model): | ||
_inherit = "mail.template" | ||
|
||
use_autosubscribe_followers = fields.Boolean(default=True) | ||
|
||
def generate_recipients(self, results, res_ids): | ||
res = super().generate_recipients(results, res_ids) | ||
autosubscribe_followers = ( | ||
self.use_autosubscribe_followers | ||
and not self.env.context.get("no_autosubscribe_followers") | ||
# In this case, autosubscribers will be added by | ||
# :func:`_message_get_default_recipients` | ||
and not self.use_default_to | ||
and not self.env.context.get("tpl_force_default_to") | ||
) | ||
if autosubscribe_followers: | ||
for res_id in res.keys(): | ||
partners = ( | ||
self.env["res.partner"].sudo().browse(res[res_id]["partner_ids"]) | ||
) | ||
ResModel = self.env[self.model] | ||
followers = ResModel._message_get_autosubscribe_followers(partners) | ||
follower_ids = [ | ||
follower.id for follower in followers if follower not in partners | ||
] | ||
res[res_id]["partner_ids"] += follower_ids | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import models | ||
|
||
|
||
class MailThread(models.AbstractModel): | ||
_inherit = "mail.thread" | ||
|
||
def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None): | ||
# Overload to automatically subscribe autosubscribe followers. | ||
autosubscribe_followers = not self.env.context.get("no_autosubscribe_followers") | ||
if partner_ids and autosubscribe_followers: | ||
partners = self.env["res.partner"].sudo().browse(partner_ids) | ||
followers = self._message_get_autosubscribe_followers(partners) | ||
follower_ids = [ | ||
follower.id | ||
for follower in followers | ||
if follower not in partners and follower not in self.message_partner_ids | ||
] | ||
partner_ids += follower_ids | ||
return super().message_subscribe( | ||
partner_ids=partner_ids, | ||
channel_ids=channel_ids, | ||
subtype_ids=subtype_ids, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import api, models | ||
|
||
|
||
class BaseModel(models.AbstractModel): | ||
_inherit = "base" | ||
|
||
@api.model | ||
def _message_get_autosubscribe_followers_domain(self, partners): | ||
return [ | ||
("id", "child_of", partners.commercial_partner_id.ids), | ||
("mail_autosubscribe_ids.model", "=", self._name), | ||
] | ||
|
||
@api.model | ||
def _message_get_autosubscribe_followers(self, partners): | ||
domain = self._message_get_autosubscribe_followers_domain(partners) | ||
return self.env["res.partner"].sudo().search(domain) | ||
|
||
def _message_get_default_recipients(self): | ||
# Overload to include auto follow document partners in the composer | ||
# Note: This only works if the template is configured with 'Default recipients' | ||
res = super()._message_get_default_recipients() | ||
if self.env.context.get("no_autosubscribe_followers"): | ||
return res | ||
for rec in self: | ||
partner_ids = res[rec.id]["partner_ids"] | ||
partners = self.env["res.partner"].sudo().browse(partner_ids) | ||
followers = rec._message_get_autosubscribe_followers(partners) | ||
follower_ids = [ | ||
follower.id for follower in followers if follower not in partners | ||
] | ||
partner_ids += follower_ids | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import fields, models | ||
|
||
|
||
class ResPartner(models.Model): | ||
_inherit = "res.partner" | ||
|
||
mail_autosubscribe_ids = fields.Many2many( | ||
"mail.autosubscribe", | ||
string="Autosubscribe Models", | ||
column1="partner_id", | ||
column2="model_id", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Go to Configuration > Technical > Automation > Autosubscribe Models and configure | ||
the models for which you want the feature to work. | ||
|
||
Then, on each partner, you can check the company documents subscriptions in the | ||
field `In copy of`. | ||
|
||
This feature can be disabled on specific templates, if required, by disabling the | ||
Autosubscribe followers field. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
* `Camptocamp <https://www.camptocamp.com>`_ | ||
|
||
* Iván Todorovich <[email protected]> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
This module allows you to configure partners that will be automatically in copy | ||
of their company's business documents. | ||
|
||
For example, you can configure an accountant to be in copy of all invoices | ||
sent for a given commercial partner, regardless of the invoicing address. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
* Consider implementing domain-based autosubscription rules. | ||
This was considered during first development but it wasn't a requirement at the time. | ||
If pursuit, this has to be done carefully to avoid affecting performance. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
access_mail_autosubscribe_user,access_mail_autosubscribe_user,model_mail_autosubscribe,base.group_user,1,0,0,0 | ||
access_mail_autosubscribe_system,access_mail_autosubscribe_system,model_mail_autosubscribe,base.group_system,1,1,1,1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import test_mail_autosubscribe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import fake_order |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import fields, models | ||
|
||
|
||
class FakeOrder(models.Model): | ||
_name = "fake.order" | ||
_inherit = "mail.thread" | ||
_description = "Fake sale.order like model" | ||
|
||
partner_id = fields.Many2one("res.partner", required=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# Copyright 2021 Camptocamp (http://www.camptocamp.com). | ||
# @author Iván Todorovich <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo_test_helper import FakeModelLoader | ||
|
||
from odoo.tests.common import Form, SavepointCase, tagged | ||
|
||
|
||
@tagged("post_install", "-at_install") | ||
class TestMailAutosubscribe(SavepointCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
# Setup env | ||
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) | ||
# Load fake order model | ||
cls.loader = FakeModelLoader(cls.env, cls.__module__) | ||
cls.loader.backup_registry() | ||
from .models.fake_order import FakeOrder | ||
|
||
cls.loader.update_registry((FakeOrder,)) | ||
cls.fake_order_model = cls.env["ir.model"].search( | ||
[("model", "=", "fake.order")] | ||
) | ||
# Email Template | ||
cls.mail_template = cls.env["mail.template"].create( | ||
{ | ||
"model_id": cls.fake_order_model.id, | ||
"name": "Fake Order: Send by Mail", | ||
"subject": "Fake Order: ${object.partner_id.name}", | ||
"partner_to": "${object.partner_id.id}", | ||
"body_html": "Hello, this is a fake order", | ||
} | ||
) | ||
# Partners | ||
cls.commercial_partner = cls.env.ref("base.res_partner_4") | ||
cls.partner_1 = cls.env.ref("base.res_partner_address_13") | ||
cls.partner_2 = cls.env.ref("base.res_partner_address_14") | ||
cls.partner_3 = cls.env.ref("base.res_partner_address_24") | ||
# Autosubscribe rules | ||
cls.autosubscribe_fake_order = cls.env["mail.autosubscribe"].create( | ||
{"model_id": cls.fake_order_model.id} | ||
) | ||
cls.partner_3.mail_autosubscribe_ids = [(4, cls.autosubscribe_fake_order.id)] | ||
# Empty fake.order | ||
cls.order = cls.env["fake.order"].create({"partner_id": cls.partner_2.id}) | ||
|
||
@classmethod | ||
def tearDownClass(cls): | ||
cls.loader.restore_registry() | ||
return super().tearDownClass() | ||
|
||
def test_message_subscribe(self): | ||
"""Test autosubscribe on a basic workflow""" | ||
self.assertFalse(self.order.message_partner_ids, "No subscribers yet") | ||
self.order.message_subscribe([self.order.partner_id.id]) | ||
self.assertEqual( | ||
self.order.message_partner_ids, | ||
self.partner_2 | self.partner_3, | ||
"Partner 3 is automatically subscribed", | ||
) | ||
|
||
def test_message_subscribe_disabled(self): | ||
"""Test autosubscribe on a basic workflow (disabled)""" | ||
self.partner_3.mail_autosubscribe_ids = [(5, False)] | ||
self.assertFalse(self.order.message_partner_ids, "No subscribers yet") | ||
self.order.message_subscribe([self.order.partner_id.id]) | ||
self.assertEqual( | ||
self.order.message_partner_ids, | ||
self.partner_2, | ||
"Partner 2 is the only subscriber", | ||
) | ||
|
||
def test_mail_template(self): | ||
"""Test autosubscribe when partner is set in the mail.template partners_to""" | ||
self.mail_template.send_mail(self.order.id) | ||
message = self.order.message_ids[0] | ||
self.assertEqual(message.partner_ids, self.partner_2 | self.partner_3) | ||
|
||
def test_mail_template_disabled(self): | ||
"""Test autosubscribe when the partner is not an autosubscribe follower""" | ||
self.partner_3.mail_autosubscribe_ids = [(5, False)] | ||
self.mail_template.send_mail(self.order.id) | ||
message = self.order.message_ids[0] | ||
self.assertEqual(message.partner_ids, self.partner_2) | ||
|
||
def test_mail_template_no_autosubscribe_followers(self): | ||
"""Test autosubscribe doesn't apply if it's disabled on the template""" | ||
self.mail_template.use_autosubscribe_followers = False | ||
self.mail_template.send_mail(self.order.id) | ||
message = self.order.message_ids[0] | ||
self.assertEqual(message.partner_ids, self.partner_2) | ||
|
||
def test_mail_template_default_recipients(self): | ||
"""Test autosubscribe when using default recipients""" | ||
self.mail_template.use_default_to = True | ||
self.mail_template.send_mail(self.order.id) | ||
message = self.order.message_ids[0] | ||
self.assertEqual(message.partner_ids, self.partner_2 | self.partner_3) | ||
|
||
def test_mail_message_composer(self): | ||
"""Test autosubscribe when using the mail composer""" | ||
self.assertFalse(self.order.message_partner_ids, "No subscribers yet") | ||
composer = Form( | ||
self.env["mail.compose.message"].with_context( | ||
default_model="fake.order", | ||
default_res_id=self.order.id, | ||
default_use_template=True, | ||
default_template_id=self.mail_template.id, | ||
default_composition_mode="comment", | ||
) | ||
) | ||
composer.save().send_mail() | ||
message = self.order.message_ids[0] | ||
self.assertEqual(message.partner_ids, self.partner_2 | self.partner_3) | ||
|
||
def test_mail_message_composer_no_autosubscribe_followers(self): | ||
"""Test autosubscribe when using the mail composer and it's disabled""" | ||
self.mail_template.use_autosubscribe_followers = False | ||
composer = Form( | ||
self.env["mail.compose.message"].with_context( | ||
default_model="fake.order", | ||
default_res_id=self.order.id, | ||
default_use_template=True, | ||
default_template_id=self.mail_template.id, | ||
default_composition_mode="comment", | ||
) | ||
) | ||
composer.save().send_mail() | ||
message = self.order.message_ids[0] | ||
self.assertEqual(message.partner_ids, self.partner_2) |
Oops, something went wrong.