odoo-addon-mail-gateway 16.0.1.3.0__py3-none-any.whl → 17.0.1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of odoo-addon-mail-gateway might be problematic. Click here for more details.
- odoo/addons/mail_gateway/README.rst +31 -24
- odoo/addons/mail_gateway/__init__.py +0 -1
- odoo/addons/mail_gateway/__manifest__.py +6 -14
- odoo/addons/mail_gateway/controllers/discuss.py +2 -2
- odoo/addons/mail_gateway/controllers/gateway.py +3 -0
- odoo/addons/mail_gateway/hooks.py +3 -3
- odoo/addons/mail_gateway/i18n/es.po +68 -406
- odoo/addons/mail_gateway/i18n/it.po +5 -336
- odoo/addons/mail_gateway/i18n/mail_gateway.pot +149 -84
- odoo/addons/mail_gateway/models/__init__.py +4 -3
- odoo/addons/mail_gateway/models/{mail_channel.py → discuss_channel.py} +30 -8
- odoo/addons/mail_gateway/models/ir_websocket.py +1 -1
- odoo/addons/mail_gateway/models/mail_gateway.py +4 -4
- odoo/addons/mail_gateway/models/mail_gateway_abstract.py +2 -2
- odoo/addons/mail_gateway/models/mail_message.py +9 -8
- odoo/addons/mail_gateway/models/mail_notification.py +3 -3
- odoo/addons/mail_gateway/models/mail_thread.py +40 -8
- odoo/addons/mail_gateway/models/res_partner.py +10 -18
- odoo/addons/mail_gateway/models/res_users.py +0 -1
- odoo/addons/mail_gateway/models/res_users_settings.py +12 -0
- odoo/addons/mail_gateway/readme/CONTRIBUTORS.md +2 -0
- odoo/addons/mail_gateway/readme/{CREDITS.rst → CREDITS.md} +2 -1
- odoo/addons/mail_gateway/readme/DESCRIPTION.md +8 -0
- odoo/addons/mail_gateway/readme/USAGE.md +12 -0
- odoo/addons/mail_gateway/security/ir.model.access.csv +4 -2
- odoo/addons/mail_gateway/security/security.xml +9 -9
- odoo/addons/mail_gateway/static/description/index.html +23 -16
- odoo/addons/mail_gateway/static/src/components/chatter/chatter.esm.js +15 -0
- odoo/addons/mail_gateway/static/src/components/chatter/chatter.xml +36 -22
- odoo/addons/mail_gateway/static/src/components/composer/composer.esm.js +108 -0
- odoo/addons/mail_gateway/static/src/components/gateway_follower/gateway_follower.esm.js +35 -22
- odoo/addons/mail_gateway/static/src/components/gateway_follower/gateway_follower.xml +3 -5
- odoo/addons/mail_gateway/static/src/components/message/message.xml +15 -15
- odoo/addons/mail_gateway/static/src/components/message/message_patch.esm.js +67 -0
- odoo/addons/mail_gateway/static/src/components/message_notification_popover_content/message_notification_popover_content.xml +3 -7
- odoo/addons/mail_gateway/static/src/core/common/composer_model_patch.esm.js +23 -0
- odoo/addons/mail_gateway/static/src/core/common/discuss_app_model_patch.esm.js +31 -0
- odoo/addons/mail_gateway/static/src/core/common/message_actions.esm.js +23 -0
- odoo/addons/mail_gateway/static/src/core/common/message_model_patch.esm.js +21 -0
- odoo/addons/mail_gateway/static/src/core/common/notification_model_patch.esm.js +35 -0
- odoo/addons/mail_gateway/static/src/core/common/persona_model_patch.esm.js +12 -0
- odoo/addons/mail_gateway/static/src/core/common/store_service_patch.esm.js +14 -0
- odoo/addons/mail_gateway/static/src/core/common/thread_model_patch.esm.js +49 -0
- odoo/addons/mail_gateway/static/src/core/common/thread_service_patch.esm.js +19 -0
- odoo/addons/mail_gateway/static/src/core/web/discuss_app_category_model_patch.esm.js +21 -0
- odoo/addons/mail_gateway/static/src/core/web/discuss_sidebar_categories.esm.js +16 -0
- odoo/addons/mail_gateway/static/src/core/web/discuss_sidebar_category_item_patch.xml +12 -0
- odoo/addons/mail_gateway/static/src/core/web/gateway_core_web_service.esm.js +40 -0
- odoo/addons/mail_gateway/static/src/models/gateway.esm.js +21 -14
- odoo/addons/mail_gateway/static/src/models/gateway_channel.esm.js +21 -13
- odoo/addons/mail_gateway/static/src/models/gateway_follower.esm.js +24 -0
- odoo/addons/mail_gateway/views/mail_gateway.xml +4 -4
- odoo/addons/mail_gateway/views/mail_guest_views.xml +15 -0
- odoo/addons/mail_gateway/wizards/mail_compose_gateway_message.py +19 -4
- odoo/addons/mail_gateway/wizards/mail_compose_gateway_message.xml +1 -2
- odoo/addons/mail_gateway/wizards/mail_guest_manage.py +2 -3
- odoo/addons/mail_gateway/wizards/mail_guest_manage.xml +2 -2
- odoo/addons/mail_gateway/wizards/mail_message_gateway_link.py +1 -2
- odoo/addons/mail_gateway/wizards/mail_message_gateway_send.py +0 -1
- {odoo_addon_mail_gateway-16.0.1.3.0.dist-info → odoo_addon_mail_gateway-17.0.1.0.1.dist-info}/METADATA +38 -30
- odoo_addon_mail_gateway-17.0.1.0.1.dist-info/RECORD +74 -0
- {odoo_addon_mail_gateway-16.0.1.3.0.dist-info → odoo_addon_mail_gateway-17.0.1.0.1.dist-info}/WHEEL +1 -1
- odoo_addon_mail_gateway-17.0.1.0.1.dist-info/top_level.txt +1 -0
- odoo/addons/mail_gateway/i18n/es_VE.po +0 -879
- odoo/addons/mail_gateway/readme/CONTRIBUTORS.rst +0 -2
- odoo/addons/mail_gateway/readme/DESCRIPTION.rst +0 -5
- odoo/addons/mail_gateway/readme/USAGE.rst +0 -9
- odoo/addons/mail_gateway/static/src/components/composer/composer.xml +0 -24
- odoo/addons/mail_gateway/static/src/components/discuss_sidebar/discuss_sidebar.xml +0 -17
- odoo/addons/mail_gateway/static/src/models/channel.esm.js +0 -33
- odoo/addons/mail_gateway/static/src/models/channel_member_view.esm.js +0 -39
- odoo/addons/mail_gateway/static/src/models/chatter.esm.js +0 -41
- odoo/addons/mail_gateway/static/src/models/composer.esm.js +0 -32
- odoo/addons/mail_gateway/static/src/models/composer_gateway_follower.esm.js +0 -32
- odoo/addons/mail_gateway/static/src/models/composer_view.esm.js +0 -103
- odoo/addons/mail_gateway/static/src/models/discuss.esm.js +0 -51
- odoo/addons/mail_gateway/static/src/models/discuss_sidebar_category.esm.js +0 -128
- odoo/addons/mail_gateway/static/src/models/discuss_sidebar_category_item.esm.js +0 -51
- odoo/addons/mail_gateway/static/src/models/gateway_channel_view.esm.js +0 -15
- odoo/addons/mail_gateway/static/src/models/guest.esm.js +0 -10
- odoo/addons/mail_gateway/static/src/models/message.esm.js +0 -76
- odoo/addons/mail_gateway/static/src/models/message_action.esm.js +0 -45
- odoo/addons/mail_gateway/static/src/models/message_action_list.esm.js +0 -37
- odoo/addons/mail_gateway/static/src/models/message_action_view.esm.js +0 -91
- odoo/addons/mail_gateway/static/src/models/message_view.esm.js +0 -13
- odoo/addons/mail_gateway/static/src/models/messaging_initializer.esm.js +0 -24
- odoo/addons/mail_gateway/static/src/models/notification.esm.js +0 -20
- odoo/addons/mail_gateway/static/src/models/partner.esm.js +0 -11
- odoo/addons/mail_gateway/static/src/models/thread.esm.js +0 -77
- odoo_addon_mail_gateway-16.0.1.3.0.dist-info/RECORD +0 -78
- odoo_addon_mail_gateway-16.0.1.3.0.dist-info/top_level.txt +0 -1
|
@@ -7,13 +7,13 @@ from odoo import fields, models
|
|
|
7
7
|
class MailNotification(models.Model):
|
|
8
8
|
_inherit = "mail.notification"
|
|
9
9
|
|
|
10
|
-
gateway_channel_id = fields.Many2one("
|
|
10
|
+
gateway_channel_id = fields.Many2one("discuss.channel")
|
|
11
11
|
notification_type = fields.Selection(
|
|
12
12
|
selection_add=[("gateway", "Gateway")], ondelete={"gateway": "cascade"}
|
|
13
13
|
)
|
|
14
14
|
gateway_message_id = fields.Char(readonly=True)
|
|
15
15
|
gateway_failure_reason = fields.Text(
|
|
16
|
-
readonly=
|
|
16
|
+
readonly=True,
|
|
17
17
|
help="Failure reason. This is usually the exception thrown by the"
|
|
18
18
|
" email server, stored to ease the debugging of mailing issues.",
|
|
19
19
|
)
|
|
@@ -26,7 +26,7 @@ class MailNotification(models.Model):
|
|
|
26
26
|
|
|
27
27
|
def _notification_format(self):
|
|
28
28
|
result = super()._notification_format()
|
|
29
|
-
for record, formatted_value in zip(self, result):
|
|
29
|
+
for record, formatted_value in zip(self, result, strict=True):
|
|
30
30
|
formatted_value["gateway_type"] = record.gateway_type
|
|
31
31
|
formatted_value["channel_name"] = record.gateway_channel_id.name
|
|
32
32
|
return result
|
|
@@ -6,6 +6,18 @@ from odoo import models
|
|
|
6
6
|
class MailThread(models.AbstractModel):
|
|
7
7
|
_inherit = "mail.thread"
|
|
8
8
|
|
|
9
|
+
def _get_message_create_valid_field_names(self):
|
|
10
|
+
# Add gateway fields
|
|
11
|
+
field_names = super()._get_message_create_valid_field_names()
|
|
12
|
+
field_names.update(
|
|
13
|
+
{"gateway_type", "gateway_notifications", "gateway_message_id"}
|
|
14
|
+
)
|
|
15
|
+
return field_names
|
|
16
|
+
|
|
17
|
+
def _get_notify_valid_parameters(self):
|
|
18
|
+
notify_valid_parameters = super()._get_notify_valid_parameters()
|
|
19
|
+
return notify_valid_parameters | {"gateway_notifications"}
|
|
20
|
+
|
|
9
21
|
def _notify_thread_by_email(self, message, recipients_data, **kwargs):
|
|
10
22
|
partners_data = [r for r in recipients_data if r["notif"] == "gateway"]
|
|
11
23
|
if partners_data:
|
|
@@ -25,7 +37,7 @@ class MailThread(models.AbstractModel):
|
|
|
25
37
|
)
|
|
26
38
|
|
|
27
39
|
def _notify_get_recipients(self, message, msg_vals, **kwargs):
|
|
28
|
-
if "gateway_notifications"
|
|
40
|
+
if kwargs.get("gateway_notifications"):
|
|
29
41
|
result = []
|
|
30
42
|
for notification in kwargs["gateway_notifications"]:
|
|
31
43
|
if not notification.get("channel_type"):
|
|
@@ -56,30 +68,50 @@ class MailThread(models.AbstractModel):
|
|
|
56
68
|
return result
|
|
57
69
|
return super()._notify_get_recipients(message, msg_vals, **kwargs)
|
|
58
70
|
|
|
71
|
+
def _get_mail_thread_data(self, request_list):
|
|
72
|
+
data = super()._get_mail_thread_data(request_list)
|
|
73
|
+
data["gateway_followers"] = [
|
|
74
|
+
f["partner"]
|
|
75
|
+
for f in data.get("followers", [])
|
|
76
|
+
if f["partner"]["gateway_channels"]
|
|
77
|
+
]
|
|
78
|
+
return data
|
|
79
|
+
|
|
59
80
|
def _check_can_update_message_content(self, messages):
|
|
60
81
|
# We can delete the messages comming from a gateway on not channels
|
|
61
|
-
if self._name != "
|
|
82
|
+
if self._name != "discuss.channel":
|
|
62
83
|
new_messages = messages.filtered(lambda r: not r.gateway_message_ids)
|
|
63
84
|
else:
|
|
64
85
|
new_messages = messages
|
|
65
86
|
return super()._check_can_update_message_content(new_messages)
|
|
66
87
|
|
|
67
88
|
def _message_update_content(
|
|
68
|
-
self,
|
|
89
|
+
self,
|
|
90
|
+
message,
|
|
91
|
+
body,
|
|
92
|
+
attachment_ids=None,
|
|
93
|
+
partner_ids=None,
|
|
94
|
+
strict=True,
|
|
95
|
+
**kwargs,
|
|
69
96
|
):
|
|
70
97
|
result = super()._message_update_content(
|
|
71
|
-
message
|
|
98
|
+
message=message,
|
|
99
|
+
body=body,
|
|
100
|
+
attachment_ids=attachment_ids,
|
|
101
|
+
partner_ids=partner_ids,
|
|
102
|
+
strict=strict,
|
|
103
|
+
**kwargs,
|
|
72
104
|
)
|
|
73
105
|
if body == "":
|
|
74
106
|
# Unlink the message
|
|
75
|
-
for
|
|
76
|
-
|
|
107
|
+
for gateway_msg in message.gateway_message_ids:
|
|
108
|
+
gateway_msg.gateway_message_id = False
|
|
77
109
|
self.env["bus.bus"]._sendone(
|
|
78
110
|
self.env.user.partner_id,
|
|
79
111
|
"mail.message/insert",
|
|
80
112
|
{
|
|
81
|
-
"id":
|
|
82
|
-
"gateway_thread_data":
|
|
113
|
+
"id": gateway_msg.id,
|
|
114
|
+
"gateway_thread_data": gateway_msg.sudo().gateway_thread_data,
|
|
83
115
|
},
|
|
84
116
|
)
|
|
85
117
|
return result
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright 2024 Dixmit
|
|
2
2
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
3
3
|
|
|
4
|
-
from odoo import fields, models
|
|
4
|
+
from odoo import api, fields, models
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class ResPartner(models.Model):
|
|
@@ -30,13 +30,13 @@ class ResPartner(models.Model):
|
|
|
30
30
|
def _get_channels_as_member(self):
|
|
31
31
|
channels = super()._get_channels_as_member()
|
|
32
32
|
if self.env.user.has_group("mail_gateway.gateway_user"):
|
|
33
|
-
channels |= self.env["
|
|
33
|
+
channels |= self.env["discuss.channel"].search(
|
|
34
34
|
[
|
|
35
35
|
("channel_type", "=", "gateway"),
|
|
36
36
|
(
|
|
37
37
|
"channel_member_ids",
|
|
38
38
|
"in",
|
|
39
|
-
self.env["
|
|
39
|
+
self.env["discuss.channel.member"]
|
|
40
40
|
.sudo()
|
|
41
41
|
._search(
|
|
42
42
|
[
|
|
@@ -66,24 +66,16 @@ class ResPartnerGatewayChannel(models.Model):
|
|
|
66
66
|
"res.company", related="gateway_id.company_id", store=True
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
@api.depends_context("mail_gateway_partner_info")
|
|
70
|
+
def _compute_display_name(self):
|
|
70
71
|
# Be able to tell to which partner belongs the gateway partner channel
|
|
71
72
|
# e.g.: picking it from a selector
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
for record in self:
|
|
78
|
-
result.append(
|
|
79
|
-
(
|
|
80
|
-
record.id,
|
|
81
|
-
"{} ({})".format(
|
|
82
|
-
record.partner_id.display_name, origin_dict[record.id]
|
|
83
|
-
),
|
|
84
|
-
)
|
|
73
|
+
if not self.env.context.get("mail_gateway_partner_info"):
|
|
74
|
+
return super()._compute_display_name()
|
|
75
|
+
for gateway_channel in self:
|
|
76
|
+
gateway_channel.display_name = (
|
|
77
|
+
f"{gateway_channel.partner_id.display_name} ({gateway_channel.name})"
|
|
85
78
|
)
|
|
86
|
-
return result
|
|
87
79
|
|
|
88
80
|
_sql_constraints = [
|
|
89
81
|
(
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
|
2
|
+
from odoo import fields, models
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ResUsersSettings(models.Model):
|
|
6
|
+
_inherit = "res.users.settings"
|
|
7
|
+
|
|
8
|
+
is_discuss_sidebar_category_gateway_open = fields.Boolean(
|
|
9
|
+
string="Gateway Category Open",
|
|
10
|
+
default=True,
|
|
11
|
+
help="The gateway category in the sidebar will be open",
|
|
12
|
+
)
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
This work has been funded by AEOdoo (Asociación Española de Odoo -
|
|
1
|
+
This work has been funded by AEOdoo (Asociación Española de Odoo -
|
|
2
|
+
<https://www.aeodoo.org>)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
This module will allow you to integrate an external chat system in your
|
|
2
|
+
Odoo system. It requires extra modules with the specific configuration
|
|
3
|
+
of each chat system, like mail_gateway_telegram or
|
|
4
|
+
mail_gateway_whatsapp.
|
|
5
|
+
|
|
6
|
+
This way, a group of users can respond customers or any other set of
|
|
7
|
+
partners within Odoo, but the messages will be sent through the external
|
|
8
|
+
chat system.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
When external messages are received, they will be directly sent to the
|
|
2
|
+
discuss menu. Answering to these messages will send the answer to the
|
|
3
|
+
external contact. We can assign this messages to any record using the
|
|
4
|
+
message actions. Also, we can assign the sender to a partner using the
|
|
5
|
+
followers menu and selecting the partner.
|
|
6
|
+
|
|
7
|
+
On a standard record associated to a partner with external chat, we can
|
|
8
|
+
send messages to the external contact directly selecting the methods of
|
|
9
|
+
the partner. To use this, we just need to use the
|
|
10
|
+
|
|
11
|
+
It is recomended to enable chatter notification to all users that will
|
|
12
|
+
receive messages from gateways.
|
|
@@ -3,8 +3,10 @@ access_res_partner_gateway_channel_portal,res.partner.gateway.channel.portal,mod
|
|
|
3
3
|
access_res_partner_gateway_channel_user,res.partner.gateway.channel,model_res_partner_gateway_channel,base.group_user,1,0,0,0
|
|
4
4
|
manage_res_partner_gateway_channel_user,res.partner.gateway.channel,model_res_partner_gateway_channel,gateway_user,1,1,1,1
|
|
5
5
|
access_mail_message_gateway_send_user,mail.message.gateway.send,model_mail_message_gateway_send,base.group_user,1,1,1,0
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
access_mail_gateway_portal,mail.gateway.portal,model_mail_gateway,base.group_portal,1,0,0,0
|
|
7
|
+
access_mail_gateway_public,mail.gateway.public,model_mail_gateway,base.group_public,1,0,0,0
|
|
8
|
+
access_mail_gateway_user,mail.gateway.user,model_mail_gateway,base.group_user,1,0,0,0
|
|
9
|
+
access_mail_guest_manage,mail.gateway.internal,model_mail_guest_manage,base.group_user,1,1,1,1
|
|
8
10
|
access_mail_message_gateway_link,mail.message.link.all,model_mail_message_gateway_link,base.group_user,1,1,1,1
|
|
9
11
|
access_mail_gateway_system,mail_gateway,model_mail_gateway,base.group_system,1,1,1,1
|
|
10
12
|
access_mail_compose_gateway_message,access.mail.compose.gateway.message,model_mail_compose_gateway_message,base.group_user,1,1,1,0
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
|
|
12
12
|
/>
|
|
13
13
|
</record>
|
|
14
|
-
<record id="
|
|
15
|
-
<field name="name">
|
|
16
|
-
<field name="model_id" ref="mail.
|
|
14
|
+
<record id="discuss_channel_gateway_rule" model="ir.rule">
|
|
15
|
+
<field name="name">discuss.channel: access gateway</field>
|
|
16
|
+
<field name="model_id" ref="mail.model_discuss_channel" />
|
|
17
17
|
<field name="groups" eval="[(4, ref('mail_gateway.gateway_user'))]" />
|
|
18
18
|
<field
|
|
19
19
|
name="domain_force"
|
|
20
|
-
>[('channel_type', '=', 'gateway'),
|
|
20
|
+
>[('channel_type', '=', 'gateway'), ('company_id', 'in', company_ids + [False]) ]</field>
|
|
21
21
|
<field name="perm_read" eval="True" />
|
|
22
22
|
<field name="perm_create" eval="False" />
|
|
23
23
|
<field name="perm_write" eval="True" />
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<field name="model_id" ref="mail_gateway.model_mail_gateway" />
|
|
29
29
|
<field
|
|
30
30
|
name="domain_force"
|
|
31
|
-
>[
|
|
31
|
+
>[('company_id', 'in', company_ids + [False]) ]</field>
|
|
32
32
|
<field name="perm_read" eval="True" />
|
|
33
33
|
<field name="perm_create" eval="True" />
|
|
34
34
|
<field name="perm_write" eval="True" />
|
|
@@ -39,17 +39,17 @@
|
|
|
39
39
|
<field name="model_id" ref="mail_gateway.model_res_partner_gateway_channel" />
|
|
40
40
|
<field
|
|
41
41
|
name="domain_force"
|
|
42
|
-
>[
|
|
42
|
+
>[('company_id', 'in', company_ids + [False]) ]</field>
|
|
43
43
|
<field name="perm_read" eval="True" />
|
|
44
44
|
<field name="perm_create" eval="True" />
|
|
45
45
|
<field name="perm_write" eval="True" />
|
|
46
46
|
<field name="perm_unlink" eval="True" />
|
|
47
47
|
</record>
|
|
48
|
-
<record id="
|
|
48
|
+
<record id="ir_rule_discuss_channel_partner_group_user" model="ir.rule">
|
|
49
49
|
<field
|
|
50
50
|
name="name"
|
|
51
|
-
>
|
|
52
|
-
<field name="model_id" ref="mail.
|
|
51
|
+
>discuss.channel.member: write its own entries on gateway channels members</field>
|
|
52
|
+
<field name="model_id" ref="mail.model_discuss_channel_member" />
|
|
53
53
|
<field name="groups" eval="[(4, ref('mail_gateway.gateway_user'))]" />
|
|
54
54
|
<field name="domain_force">[('channel_id.channel_type', '=', 'gateway')]</field>
|
|
55
55
|
<field name="perm_read" eval="False" />
|
|
@@ -372,13 +372,16 @@ ul.auto-toc {
|
|
|
372
372
|
!! This file is generated by oca-gen-addon-readme !!
|
|
373
373
|
!! changes will be overwritten. !!
|
|
374
374
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
375
|
-
!! source digest: sha256:
|
|
375
|
+
!! source digest: sha256:dd9cb533ce55e29e10867b506e532d6379d7cd12fba20203d82804176c6a8dfa
|
|
376
376
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
|
377
|
-
<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/social/tree/
|
|
378
|
-
<p>This module will allow you to integrate an external chat system in your
|
|
379
|
-
It requires extra modules with the specific configuration
|
|
380
|
-
|
|
381
|
-
|
|
377
|
+
<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/social/tree/17.0/mail_gateway"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_gateway"><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/social&target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
|
378
|
+
<p>This module will allow you to integrate an external chat system in your
|
|
379
|
+
Odoo system. It requires extra modules with the specific configuration
|
|
380
|
+
of each chat system, like mail_gateway_telegram or
|
|
381
|
+
mail_gateway_whatsapp.</p>
|
|
382
|
+
<p>This way, a group of users can respond customers or any other set of
|
|
383
|
+
partners within Odoo, but the messages will be sent through the external
|
|
384
|
+
chat system.</p>
|
|
382
385
|
<p><strong>Table of contents</strong></p>
|
|
383
386
|
<div class="contents local topic" id="contents">
|
|
384
387
|
<ul class="simple">
|
|
@@ -395,20 +398,23 @@ of partners within Odoo, but the messages will be sent through the external chat
|
|
|
395
398
|
</div>
|
|
396
399
|
<div class="section" id="usage">
|
|
397
400
|
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
|
|
398
|
-
<p>When external messages are received, they will be directly sent to the
|
|
399
|
-
Answering to these messages will send the answer to the
|
|
400
|
-
We can assign this messages to any record using the
|
|
401
|
-
Also, we can assign the sender to a partner using the
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
401
|
+
<p>When external messages are received, they will be directly sent to the
|
|
402
|
+
discuss menu. Answering to these messages will send the answer to the
|
|
403
|
+
external contact. We can assign this messages to any record using the
|
|
404
|
+
message actions. Also, we can assign the sender to a partner using the
|
|
405
|
+
followers menu and selecting the partner.</p>
|
|
406
|
+
<p>On a standard record associated to a partner with external chat, we can
|
|
407
|
+
send messages to the external contact directly selecting the methods of
|
|
408
|
+
the partner. To use this, we just need to use the</p>
|
|
409
|
+
<p>It is recomended to enable chatter notification to all users that will
|
|
410
|
+
receive messages from gateways.</p>
|
|
405
411
|
</div>
|
|
406
412
|
<div class="section" id="bug-tracker">
|
|
407
413
|
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
|
|
408
414
|
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/social/issues">GitHub Issues</a>.
|
|
409
415
|
In case of trouble, please check there if your issue has already been reported.
|
|
410
416
|
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
|
411
|
-
<a class="reference external" href="https://github.com/OCA/social/issues/new?body=module:%20mail_gateway%0Aversion:%
|
|
417
|
+
<a class="reference external" href="https://github.com/OCA/social/issues/new?body=module:%20mail_gateway%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
|
412
418
|
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
|
413
419
|
</div>
|
|
414
420
|
<div class="section" id="credits">
|
|
@@ -429,7 +435,8 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
|
|
429
435
|
</div>
|
|
430
436
|
<div class="section" id="other-credits">
|
|
431
437
|
<h3><a class="toc-backref" href="#toc-entry-6">Other credits</a></h3>
|
|
432
|
-
<p>This work has been funded by AEOdoo (Asociación Española de Odoo -
|
|
438
|
+
<p>This work has been funded by AEOdoo (Asociación Española de Odoo -
|
|
439
|
+
<a class="reference external" href="https://www.aeodoo.org">https://www.aeodoo.org</a>)</p>
|
|
433
440
|
</div>
|
|
434
441
|
<div class="section" id="maintainers">
|
|
435
442
|
<h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
|
|
@@ -440,7 +447,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
|
|
440
447
|
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
|
441
448
|
mission is to support the collaborative development of Odoo features and
|
|
442
449
|
promote its widespread use.</p>
|
|
443
|
-
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/social/tree/
|
|
450
|
+
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/social/tree/17.0/mail_gateway">OCA/social</a> project on GitHub.</p>
|
|
444
451
|
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
|
445
452
|
</div>
|
|
446
453
|
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** @odoo-module **/
|
|
2
|
+
import {Chatter} from "@mail/core/web/chatter";
|
|
3
|
+
import {patch} from "@web/core/utils/patch";
|
|
4
|
+
import {GatewayFollower} from "../gateway_follower/gateway_follower.esm";
|
|
5
|
+
|
|
6
|
+
patch(Chatter, {
|
|
7
|
+
components: {...Chatter.components, GatewayFollower},
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
patch(Chatter.prototype, {
|
|
11
|
+
toggleComposer(mode = false) {
|
|
12
|
+
this.state.thread.composer.isGateway = mode === "gateway";
|
|
13
|
+
super.toggleComposer(mode);
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -3,38 +3,52 @@
|
|
|
3
3
|
|
|
4
4
|
<t
|
|
5
5
|
t-name="mail_gateway.ChatterTopbar"
|
|
6
|
-
t-inherit="mail.
|
|
6
|
+
t-inherit="mail.Chatter"
|
|
7
7
|
t-inherit-mode="extension"
|
|
8
|
-
owl="1"
|
|
9
8
|
>
|
|
10
|
-
<xpath
|
|
11
|
-
expr="//button[hasclass('o_ChatterTopbar_buttonSendMessage')]"
|
|
12
|
-
position="attributes"
|
|
13
|
-
>
|
|
14
|
-
<attribute name="t-att-class">{
|
|
15
|
-
'o-active btn-odoo': chatterTopbar.chatter.composerView and !chatterTopbar.chatter.composerView.composer.isLog and !chatterTopbar.chatter.composerView.composer.isGateway,
|
|
16
|
-
'btn-odoo': !chatterTopbar.chatter.composerView,
|
|
17
|
-
'btn-light': chatterTopbar.chatter.composerView and (chatterTopbar.chatter.composerView.composer.isLog or chatterTopbar.chatter.composerView.composer.isGateway),
|
|
18
|
-
}</attribute>
|
|
19
|
-
</xpath>
|
|
20
|
-
<xpath
|
|
21
|
-
expr="//button[hasclass('o_ChatterTopbar_buttonLogNote')]"
|
|
22
|
-
position="after"
|
|
23
|
-
>
|
|
9
|
+
<xpath expr="//button[hasclass('o-mail-Chatter-logNote')]" position="after">
|
|
24
10
|
<button
|
|
25
|
-
class="
|
|
11
|
+
class="o-mail-Chatter-gateway btn text-nowrap me-1"
|
|
26
12
|
type="button"
|
|
27
13
|
t-att-class="{
|
|
28
|
-
'
|
|
29
|
-
'btn-
|
|
30
|
-
'
|
|
14
|
+
'btn-primary active': state.composerType === 'gateway',
|
|
15
|
+
'btn-secondary': state.composerType !== 'gateway',
|
|
16
|
+
'my-2': !props.compactHeight
|
|
31
17
|
}"
|
|
32
|
-
t-
|
|
33
|
-
|
|
18
|
+
t-on-click="() => this.toggleComposer('gateway')"
|
|
19
|
+
data-hotkey="shift+w"
|
|
34
20
|
>
|
|
35
21
|
<i class="fa fa-plane" role="img" aria-label="gateway" />
|
|
36
22
|
<span> Gateway message</span>
|
|
37
23
|
</button>
|
|
38
24
|
</xpath>
|
|
25
|
+
<xpath expr="//SuggestedRecipientsList" position="before">
|
|
26
|
+
<t
|
|
27
|
+
t-if="state.composerType === 'gateway' and state.thread.gateway_followers.length"
|
|
28
|
+
>
|
|
29
|
+
<div
|
|
30
|
+
class="flex-shrink-0 px-3 pt-3 text-truncate small mb-2"
|
|
31
|
+
style="margin-left:48px"
|
|
32
|
+
>
|
|
33
|
+
<span class="fw-bold">To:</span>
|
|
34
|
+
<t
|
|
35
|
+
t-foreach="state.thread.gateway_followers"
|
|
36
|
+
t-as="gateway_follower"
|
|
37
|
+
t-key="gateway_follower.id"
|
|
38
|
+
>
|
|
39
|
+
<GatewayFollower
|
|
40
|
+
follower="gateway_follower"
|
|
41
|
+
composer="state.thread.composer"
|
|
42
|
+
/>
|
|
43
|
+
</t>
|
|
44
|
+
</div>
|
|
45
|
+
</t>
|
|
46
|
+
<t t-set="type" t-value="type === 'gateway' ? 'gateway' : type" />
|
|
47
|
+
</xpath>
|
|
48
|
+
<xpath expr="//SuggestedRecipientsList" position="attributes">
|
|
49
|
+
<attribute
|
|
50
|
+
name="t-if"
|
|
51
|
+
>props.hasFollowers and state.composerType !== 'note' and state.composerType !== 'gateway'</attribute>
|
|
52
|
+
</xpath>
|
|
39
53
|
</t>
|
|
40
54
|
</templates>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/** @odoo-module **/
|
|
2
|
+
import {patch} from "@web/core/utils/patch";
|
|
3
|
+
import {Composer} from "@mail/core/common/composer";
|
|
4
|
+
import {_t} from "@web/core/l10n/translation";
|
|
5
|
+
import {prettifyMessageContent} from "@mail/utils/common/format";
|
|
6
|
+
|
|
7
|
+
patch(Composer.prototype, {
|
|
8
|
+
get SEND_TEXT() {
|
|
9
|
+
if (this.props.type === "gateway" && !this.props.composer.message) {
|
|
10
|
+
return _t("Send gateway");
|
|
11
|
+
}
|
|
12
|
+
return super.SEND_TEXT;
|
|
13
|
+
},
|
|
14
|
+
get placeholder() {
|
|
15
|
+
if (
|
|
16
|
+
this.thread?.model !== "discuss.channel" &&
|
|
17
|
+
!this.props.placeholder &&
|
|
18
|
+
this.props.type === "gateway"
|
|
19
|
+
) {
|
|
20
|
+
return _t("Send a message to a gateway...");
|
|
21
|
+
}
|
|
22
|
+
return super.placeholder;
|
|
23
|
+
},
|
|
24
|
+
get isSendButtonDisabled() {
|
|
25
|
+
const isSendButtonDisabled = super.isSendButtonDisabled;
|
|
26
|
+
if (this.props.type !== "gateway") {
|
|
27
|
+
return isSendButtonDisabled;
|
|
28
|
+
}
|
|
29
|
+
return isSendButtonDisabled || !this.thread?.gateway_notifications.length;
|
|
30
|
+
},
|
|
31
|
+
onFocusin() {
|
|
32
|
+
super.onFocusin();
|
|
33
|
+
if (this.props.type !== "gateway") {
|
|
34
|
+
this.thread.gateway_notifications = [];
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
async onClickFullComposer() {
|
|
38
|
+
if (this.props.type !== "gateway") {
|
|
39
|
+
return super.onClickFullComposer(...arguments);
|
|
40
|
+
}
|
|
41
|
+
const attachmentIds = this.props.composer.attachments.map(
|
|
42
|
+
(attachment) => attachment.id
|
|
43
|
+
);
|
|
44
|
+
const body = this.props.composer.textInputContent;
|
|
45
|
+
const validMentions = this.store.user
|
|
46
|
+
? this.messageService.getMentionsFromText(body, {
|
|
47
|
+
mentionedChannels: this.props.composer.mentionedChannels,
|
|
48
|
+
mentionedPartners: this.props.composer.mentionedPartners,
|
|
49
|
+
})
|
|
50
|
+
: undefined;
|
|
51
|
+
// Debugger
|
|
52
|
+
const context = {
|
|
53
|
+
default_attachment_ids: attachmentIds,
|
|
54
|
+
default_body: await prettifyMessageContent(body, validMentions),
|
|
55
|
+
default_model: this.thread.model,
|
|
56
|
+
default_partner_ids: this.thread.suggestedRecipients
|
|
57
|
+
.filter((recipient) => recipient.checked)
|
|
58
|
+
.map((recipient) => recipient.persona.id),
|
|
59
|
+
default_res_ids: [this.thread.id],
|
|
60
|
+
default_subtype_xmlid: "mail.mt_comment",
|
|
61
|
+
mail_post_autofollow: this.thread.hasWriteAccess,
|
|
62
|
+
default_wizard_partner_ids: Array.from(
|
|
63
|
+
new Set(
|
|
64
|
+
this.thread.gateway_followers.map((follower) => {
|
|
65
|
+
return follower.id;
|
|
66
|
+
})
|
|
67
|
+
)
|
|
68
|
+
),
|
|
69
|
+
default_wizard_channel_ids: Array.from(
|
|
70
|
+
new Set(
|
|
71
|
+
this.thread.gateway_followers
|
|
72
|
+
.map((follower) => {
|
|
73
|
+
return follower.gateway_channels.map(
|
|
74
|
+
(channel) => channel?.id
|
|
75
|
+
);
|
|
76
|
+
})
|
|
77
|
+
.flat()
|
|
78
|
+
)
|
|
79
|
+
),
|
|
80
|
+
};
|
|
81
|
+
const action = {
|
|
82
|
+
name: _t("Gateway message"),
|
|
83
|
+
type: "ir.actions.act_window",
|
|
84
|
+
res_model: "mail.compose.gateway.message",
|
|
85
|
+
view_mode: "form",
|
|
86
|
+
views: [[false, "form"]],
|
|
87
|
+
target: "new",
|
|
88
|
+
context: context,
|
|
89
|
+
};
|
|
90
|
+
const options = {
|
|
91
|
+
onClose: (...args) => {
|
|
92
|
+
// Args === [] : click on 'X'
|
|
93
|
+
// args === { special: true } : click on 'discard'
|
|
94
|
+
const isDiscard = args.length === 0 || args[0]?.special;
|
|
95
|
+
// Otherwise message is posted (args === [undefined])
|
|
96
|
+
if (!isDiscard && this.props.composer.thread.type === "mailbox") {
|
|
97
|
+
this.notifySendFromMailbox();
|
|
98
|
+
}
|
|
99
|
+
this.clear();
|
|
100
|
+
this.props.messageToReplyTo?.cancel();
|
|
101
|
+
if (this.thread) {
|
|
102
|
+
this.threadService.fetchNewMessages(this.thread);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
await this.env.services.action.doAction(action, options);
|
|
107
|
+
},
|
|
108
|
+
});
|
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
/** @odoo-module **/
|
|
2
|
+
import {Component} from "@odoo/owl";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const {Component} = owl;
|
|
7
|
-
|
|
8
|
-
class GatewayFollowerView extends Component {
|
|
9
|
-
/**
|
|
10
|
-
* @override
|
|
11
|
-
*/
|
|
4
|
+
export class GatewayFollower extends Component {
|
|
5
|
+
static template = "mail_gateway.GatewayFollowerView";
|
|
6
|
+
static props = ["follower", "composer"];
|
|
12
7
|
setup() {
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
this.channel = false;
|
|
9
|
+
this.follower_channel_ids = this.props.follower.gateway_channels.map(
|
|
10
|
+
(channel) => channel.id
|
|
11
|
+
);
|
|
12
|
+
this._clearGatewayNotifications();
|
|
15
13
|
}
|
|
16
14
|
get composerGatewayFollower() {
|
|
17
|
-
return this.props.
|
|
15
|
+
return this.props.follower;
|
|
16
|
+
}
|
|
17
|
+
_getMessageData() {
|
|
18
|
+
return {
|
|
19
|
+
partner_id: this.props.follower.id,
|
|
20
|
+
channel_type: "gateway",
|
|
21
|
+
gateway_channel_id: this.channel,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
_clearGatewayNotifications() {
|
|
25
|
+
this.props.composer.thread.gateway_notifications =
|
|
26
|
+
this.props.composer.thread.gateway_notifications.filter(
|
|
27
|
+
(gateway_notification) => {
|
|
28
|
+
return !this.follower_channel_ids.includes(
|
|
29
|
+
gateway_notification.gateway_channel_id
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
);
|
|
18
33
|
}
|
|
19
34
|
onChangeGatewayChannel(ev) {
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
this.channel = parseInt(ev.target.options[ev.target.selectedIndex].value, 10);
|
|
36
|
+
if (this.channel) {
|
|
37
|
+
this.props.composer.thread.gateway_notifications.push(
|
|
38
|
+
this._getMessageData()
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
this._clearGatewayNotifications();
|
|
42
|
+
}
|
|
23
43
|
}
|
|
24
44
|
}
|
|
25
|
-
|
|
26
|
-
Object.assign(GatewayFollowerView, {
|
|
27
|
-
props: {record: Object},
|
|
28
|
-
template: "mail_gateway.GatewayFollowerView",
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
registerMessagingComponent(GatewayFollowerView);
|