Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH164696 - Mail v15 #50

Open
wants to merge 1 commit into
base: 15.0
Choose a base branch
from
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
18 changes: 18 additions & 0 deletions mail_res_partner_forward/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
========================
mail_res_partner_forward
========================

Allows a user to specify to forward their mail to another partner.

Usage
-----

1. Either edit partner or user
2. Enable `Email Forwarding`
3. Save, and then click the new `Edit Rules` button that appears
4. Fill the rules as appropriate to redirect email

Known Issues
------------

1. History of replacements are logged against the `mail.message` record, however this is not surfaced within the UI currently
1 change: 1 addition & 0 deletions mail_res_partner_forward/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
18 changes: 18 additions & 0 deletions mail_res_partner_forward/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "mail_res_partner_forward",
"summary": "Rule based forwarding of email to other partners",
"version": "15.0.1.0.0",
"category": "Productivity/Discuss",
"author": "Glo Networks",
"license": "AGPL-3",
"installable": True,
"depends": ["mail"],
"external_dependencies": {"python": ["odoo_test_helper"], "bin": []},
"data": [
"security/ir.model.access.csv",
"views/res_user.xml",
"views/res_partner.xml",
"views/res_partner_forwarding_rule.xml",
],
"website": "https://github.com/GlodoUK/odoo-addons",
}
6 changes: 6 additions & 0 deletions mail_res_partner_forward/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from . import res_partner
from . import res_user
from . import mail_thread
from . import mail_message
from . import mail_message_forwarding_history
from . import res_partner_forwarding_rule
9 changes: 9 additions & 0 deletions mail_res_partner_forward/models/mail_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from odoo import fields, models


class MailMessage(models.Model):
_inherit = "mail.message"

forwarded_partner_history_ids = fields.One2many(
"mail.message.forwarding.history", "message_id"
)
14 changes: 14 additions & 0 deletions mail_res_partner_forward/models/mail_message_forwarding_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from odoo import fields, models


class MailMessageForwardingHistory(models.Model):
_name = "mail.message.forwarding.history"
_description = ""

message_id = fields.Many2one(
"mail.message", required=True, index=True, ondelete="cascade"
)
replaced_partner_id = fields.Many2one(
"res.partner", required=True, ondelete="cascade"
)
partner_id = fields.Many2one("res.partner", required=True, ondelete="cascade")
63 changes: 63 additions & 0 deletions mail_res_partner_forward/models/mail_thread.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from odoo import models


class MailThread(models.AbstractModel):
_inherit = "mail.thread"

def _notify_compute_recipients(self, message, msg_vals):
recipient_data = super()._notify_compute_recipients(message, msg_vals)
if not recipient_data:
return recipient_data

partner_dict = {x.get("id"): x for x in recipient_data}
model_name = msg_vals.get("model") or message.sudo().model
new_recipient_data = {}
forwarded_history_data = []

# for each partner being notified we check if it has a
# forwarding_partner_id configured that is not being notified yet
for partner in (
self.env["res.partner"]
.sudo()
.with_context(prefetch_fields=["forwarding_rule_ids"])
.search(
[
("id", "in", list(partner_dict.keys())),
]
)
):
forwarding_to_partner_id = partner._forwarding_to_partner(model_name)
data = partner_dict[partner.id].copy()

if partner != forwarding_to_partner_id:
forwarded_history_data.append(
(
0,
0,
{
"replaced_partner_id": partner.id,
"partner_id": forwarding_to_partner_id.id,
},
)
)

data.update(
{
"id": forwarding_to_partner_id.id,
"share": forwarding_to_partner_id.partner_share,
"notif": (
forwarding_to_partner_id.user_ids
and forwarding_to_partner_id.user_ids[0].notification_type
or "email"
),
}
)

new_recipient_data[forwarding_to_partner_id.id] = data

if forwarded_history_data and message:
message.sudo().write(
{"forwarded_partner_history_ids": forwarded_history_data}
)

return list(new_recipient_data.values())
52 changes: 52 additions & 0 deletions mail_res_partner_forward/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from odoo import _, fields, models


class ResPartner(models.Model):
_inherit = "res.partner"

forwarding_enabled = fields.Boolean(
default=False,
string="Forward Emails",
)
forwarding_partner_id = fields.Many2one(
"res.partner",
string="Forwarding Partner",
)
forwarding_rule_ids = fields.One2many("res.partner.forwarding.rule", "partner_id")

def _forwarding_find_matching_rule(self, model_name):
self.ensure_one()
if not self.forwarding_enabled:
return self.env["res.partner.forwarding.rule"]

return

def _forwarding_to_partner(self, model_name):
# recursively find where to forward to
self.ensure_one()

if not self.forwarding_enabled or not self.forwarding_rule_ids:
return self

matching_rule_id = self.forwarding_rule_ids._match_rule(model_name)
if not matching_rule_id.forwarding_to_partner_id:
return self

return matching_rule_id.forwarding_to_partner_id._forwarding_to_partner(
model_name
)

def action_open_forwarding_rules(self):
self.ensure_one()

return {
"res_model": "res.partner.forwarding.rule",
"type": "ir.actions.act_window",
"view_mode": "tree",
"domain": [("partner_id", "=", self.id)],
"name": _("Email Forwarding Rules"),
"context": {
"default_partner_id": self.id,
},
"target": "new",
}
58 changes: 58 additions & 0 deletions mail_res_partner_forward/models/res_partner_forwarding_rule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from odoo import api, fields, models

SEQUENCE_MAPPING_DICT = {
"all": 2,
"include": 1,
"exclude": 0,
}


class ResPartnerForwardingRule(models.Model):
_name = "res.partner.forwarding.rule"
_description = "Contact Forwarding Rule"
_order = "sequence asc"

sequence = fields.Integer(compute="_compute_sequence", store=True, index=True)
partner_id = fields.Many2one("res.partner", required=True, index=True)
mode = fields.Selection(
[
("all", "Any Model"),
("include", "Including Model"),
("exclude", "Excluding Model"),
],
required=True,
default="all",
)
model_id = fields.Many2one("ir.model", domain="[('is_mail_thread', '=', True)]")
model_name = fields.Char(related="model_id.model", store=True)
forwarding_to_partner_id = fields.Many2one(
"res.partner", required=False, string="Forward To"
)

@api.depends("mode")
def _compute_sequence(self):
for record in self:
record.sequence = SEQUENCE_MAPPING_DICT.get(record.mode, 2)

def _match_rule(self, model_name):
matching_rule_id = self.env["res.partner.forwarding.rule"]

for rule_id in self:
if rule_id.mode == "exclude" and rule_id.model_name == model_name:
break

if rule_id.mode == "all" or (
rule_id.mode == "include" and rule_id.model_name == model_name
):
matching_rule_id = rule_id
break

return matching_rule_id

_sql_constraints = [
(
"partner_mode_model_unique",
"unique (partner_id, mode, model_id)",
"Mode and Model must be unique per partner",
)
]
29 changes: 29 additions & 0 deletions mail_res_partner_forward/models/res_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from odoo import fields, models


class ResUsers(models.Model):
_inherit = "res.users"

FORWARDING_WRITEABLE_FIELDS = [
"forwarding_enabled",
"forwarding_rule_ids",
]

forwarding_enabled = fields.Boolean(
related="partner_id.forwarding_enabled", readonly=False
)
forwarding_rule_ids = fields.One2many(
related="partner_id.forwarding_rule_ids", readonly=False
)

@property
def SELF_WRITEABLE_FIELDS(self):
return super().SELF_WRITEABLE_FIELDS + self.FORWARDING_WRITEABLE_FIELDS

@property
def SELF_READABLE_FIELDS(self):
return super().SELF_READABLE_FIELDS + self.FORWARDING_WRITEABLE_FIELDS

def action_open_forwarding_rules(self):
self.ensure_one()
return self.partner_id.action_open_forwarding_rules()
3 changes: 3 additions & 0 deletions mail_res_partner_forward/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
4 changes: 4 additions & 0 deletions mail_res_partner_forward/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_res_partner_forwarding_rules,access_res_partner_forwarding_rules,model_res_partner_forwarding_rule,base.group_user,1,1,1,1
access_mail_message_forwarding_history,access_mail_message_forwarding_history,model_mail_message_forwarding_history,,1,1,1,1
access_ir_model,access_ir_model,base.model_ir_model,base.group_user,1,0,0,0
1 change: 1 addition & 0 deletions mail_res_partner_forward/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_mail_forwarding
1 change: 1 addition & 0 deletions mail_res_partner_forward/tests/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_model
9 changes: 9 additions & 0 deletions mail_res_partner_forward/tests/models/test_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from odoo import fields, models


class FakeTestModel(models.Model):
_name = "fake.test.model"
_inherit = "mail.thread"
_description = "Mail Partner Forwarding Test Model"

partner_id = fields.Many2one("res.partner", required=True)
Loading
Loading