diff --git a/addons/crm_livechat/models/mail_channel.py b/addons/crm_livechat/models/mail_channel.py
index 7747d6926f8..c051309c813 100644
--- a/addons/crm_livechat/models/mail_channel.py
+++ b/addons/crm_livechat/models/mail_channel.py
@@ -29,7 +29,7 @@ class MailChannel(models.Model):
"""
description = ''.join(
'%s: %s\n' % (message.author_id.name or self.anonymous_name, message.body)
- for message in self.channel_message_ids.sorted('id')
+ for message in self.message_ids.sorted('id')
)
# if public user is part of the chat: consider lead to be linked to an
# anonymous user whatever the participants. Otherwise keep only share
diff --git a/addons/im_livechat/data/im_livechat_channel_demo.xml b/addons/im_livechat/data/im_livechat_channel_demo.xml
index 59d2b3b1072..2e9bffd27f4 100644
--- a/addons/im_livechat/data/im_livechat_channel_demo.xml
+++ b/addons/im_livechat/data/im_livechat_channel_demo.xml
@@ -38,7 +38,6 @@
email
You're welcome, have a nice day!
-
@@ -47,7 +46,6 @@
email
Great! Thanks for the info
-
@@ -56,7 +54,6 @@
email
Yes, you can use our Timesheets application and Awesome Timesheets to record your time efficiently!
-
@@ -65,7 +62,6 @@
email
I'm looking for an application to record my timesheet, any tips?
-
@@ -74,7 +70,6 @@
email
Hello, how may I help you?
-
@@ -99,7 +94,6 @@
email
You're welcome, enjoy Odoo!
-
@@ -108,7 +102,6 @@
email
Awesome, thanks!
-
@@ -117,7 +110,6 @@
email
Yes, we just released a new application called Social Marketing that should fit your needs! Check it out :)
-
@@ -126,7 +118,6 @@
email
I was wondering if Odoo has an application to easily manage social media for my business..
-
@@ -135,7 +126,6 @@
email
Hello, how may I help you?
-
@@ -160,7 +150,6 @@
email
Oh :(
-
@@ -169,7 +158,6 @@
email
Nope, sorry to disappoint :(
-
@@ -178,7 +166,6 @@
email
Hello, are you single?
-
@@ -187,7 +174,6 @@
email
Hello, how may I help you?
-
@@ -212,7 +198,6 @@
email
Thanks for the info, I'll look into it!
-
@@ -221,7 +206,6 @@
email
Hello Joel Willis, you're at the right place! You can customize Odoo using our Studio application in just a few clicks.
-
@@ -230,7 +214,6 @@
email
Hello, I'm looking for a software that can be easily updated with my needs.
-
@@ -255,7 +238,6 @@
email
Ok.. Will do, thanks
-
@@ -264,7 +246,6 @@
email
Hi, if you need help with your database, feel free to contact our support via http://www.odoo.com/help
-
@@ -273,7 +254,6 @@
email
Hello, it seems that I can't log in to my database. Can you help?
-
@@ -282,7 +262,6 @@
email
Hello, how may I help you?
-
@@ -307,7 +286,6 @@
email
Thanks!
-
@@ -316,7 +294,6 @@
email
Yes, of course, you can find it here: https://www.odoo.com/documentation/user/14.0/
-
@@ -325,7 +302,6 @@
email
Hello, I'm a bit lost in the Invetory module, is there some documentation I could find?
-
@@ -334,7 +310,6 @@
email
Hello, how may I help you?
-
@@ -359,7 +334,6 @@
email
Good to hear, thanks!
-
@@ -368,7 +342,6 @@
email
Joel Willis, you'll need our Inventory and Sales application to do so. You can try them for 15 days, FOR FREE :)
-
@@ -377,7 +350,6 @@
email
Hi, I need a software to easily manage my stock, and generate sales orders.
-
@@ -386,7 +358,6 @@
email
Hello, how may I help you?
-
@@ -411,7 +382,6 @@
email
I'm great, thanks for asking!
-
@@ -420,7 +390,6 @@
email
I'm fine, and you?
-
@@ -429,7 +398,6 @@
email
Heeeey Marc, how are you?
-
@@ -438,7 +406,6 @@
email
Hello, how may I help you?
-
@@ -458,7 +425,6 @@
Hi
mail.channel
-
@@ -467,7 +433,6 @@
Hello, how may I help you?
mail.channel
-
@@ -477,7 +442,6 @@
I would like to know more about the CRM application
mail.channel
-
@@ -486,7 +450,6 @@
The CRM application helps you to track leads, close opportunities and get accurate forecasts. You can test it for free on our website.
mail.channel
-
@@ -496,7 +459,6 @@
Great, thanks!
mail.channel
-
@@ -506,7 +468,6 @@
Rating: :-)
mail.channel
-
diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py
index a79734a92ef..8a8ac0fcdd8 100644
--- a/addons/im_livechat/models/im_livechat_channel.py
+++ b/addons/im_livechat/models/im_livechat_channel.py
@@ -76,7 +76,7 @@ class ImLivechatChannel(models.Model):
def _compute_nbr_channel(self):
data = self.env['mail.channel'].read_group([
('livechat_channel_id', 'in', self._ids),
- ('channel_message_ids', '!=', False)], ['__count'], ['livechat_channel_id'], lazy=False)
+ ('message_ids', '!=', False)], ['__count'], ['livechat_channel_id'], lazy=False)
channel_count = {x['livechat_channel_id'][0]: x['__count'] for x in data}
for record in self:
record.nbr_channel = channel_count.get(record.id, 0)
@@ -182,8 +182,7 @@ class ImLivechatChannel(models.Model):
self.env.cr.execute("""SELECT COUNT(DISTINCT c.id), c.livechat_operator_id
FROM mail_channel c
- LEFT OUTER JOIN mail_message_mail_channel_rel r ON c.id = r.mail_channel_id
- LEFT OUTER JOIN mail_message m ON r.mail_message_id = m.id
+ LEFT OUTER JOIN mail_message m ON c.id = m.res_id AND m.model = 'mail.channel'
WHERE c.channel_type = 'livechat'
AND c.livechat_operator_id in %s
AND m.create_date > ((now() at time zone 'UTC') - interval '30 minutes')
diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py
index 8b9f4e102cd..c77e0082702 100644
--- a/addons/im_livechat/models/mail_channel.py
+++ b/addons/im_livechat/models/mail_channel.py
@@ -131,8 +131,8 @@ class MailChannel(models.Model):
FROM mail_channel C
WHERE NOT EXISTS (
SELECT *
- FROM mail_message_mail_channel_rel R
- WHERE R.mail_channel_id = C.id
+ FROM mail_message M
+ WHERE M.res_id = C.id AND m.model = 'mail.channel'
) AND C.channel_type = 'livechat' AND livechat_channel_id IS NOT NULL AND
COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp
< ((now() at time zone 'UTC') - interval %s)""", ("%s hours" % hours,))
@@ -177,7 +177,7 @@ class MailChannel(models.Model):
if self.livechat_active:
self.livechat_active = False
# avoid useless notification if the channel is empty
- if not self.channel_message_ids:
+ if not self.message_ids:
return
# Notify that the visitor has left the conversation
self.message_post(author_id=self.env.ref('base.partner_root').id,
diff --git a/addons/im_livechat/report/im_livechat_report_channel.py b/addons/im_livechat/report/im_livechat_report_channel.py
index 07c01110b8e..9e3d2c79cbb 100644
--- a/addons/im_livechat/report/im_livechat_report_channel.py
+++ b/addons/im_livechat/report/im_livechat_report_channel.py
@@ -59,9 +59,11 @@ class ImLivechatReportChannel(models.Model):
count(distinct C.livechat_operator_id) as nbr_speaker,
count(distinct M.id) as nbr_message,
CASE
- WHEN EXISTS (select distinct M.author_id FROM mail_message M, mail_message_mail_channel_rel R
- WHERE M.author_id=C.livechat_operator_id AND R.mail_channel_id = C.id
- AND R.mail_message_id = M.id and C.livechat_operator_id = M.author_id)
+ WHEN EXISTS (select distinct M.author_id FROM mail_message M
+ WHERE M.author_id=C.livechat_operator_id
+ AND M.res_id = C.id
+ AND M.model = 'mail.channel'
+ AND C.livechat_operator_id = M.author_id)
THEN 0
ELSE 1
END as is_without_answer,
@@ -88,10 +90,9 @@ class ImLivechatReportChannel(models.Model):
END as is_unrated,
C.livechat_operator_id as partner_id
FROM mail_channel C
- JOIN mail_message_mail_channel_rel R ON (C.id = R.mail_channel_id)
- JOIN mail_message M ON (M.id = R.mail_message_id)
+ JOIN mail_message M ON (M.res_id = C.id AND m.model = 'mail.channel')
JOIN im_livechat_channel L ON (L.id = C.livechat_channel_id)
- LEFT JOIN mail_message MO ON (R.mail_message_id = MO.id AND MO.author_id = C.livechat_operator_id)
+ LEFT JOIN mail_message MO ON (M.res_id = C.id AND m.model = 'mail.channel' AND MO.author_id = C.livechat_operator_id)
LEFT JOIN rating_rating Rate ON (Rate.res_id = C.id and Rate.res_model = 'mail.channel' and Rate.parent_res_model = 'im_livechat.channel')
WHERE C.livechat_operator_id is not null
GROUP BY C.livechat_operator_id, C.id, C.name, C.livechat_channel_id, L.name, C.create_date, C.uuid, Rate.rating
diff --git a/addons/im_livechat/report/im_livechat_report_operator.py b/addons/im_livechat/report/im_livechat_report_operator.py
index cafaf898da2..8dec7061b16 100644
--- a/addons/im_livechat/report/im_livechat_report_operator.py
+++ b/addons/im_livechat/report/im_livechat_report_operator.py
@@ -35,9 +35,8 @@ class ImLivechatReportOperator(models.Model):
EXTRACT('epoch' FROM MAX(M.create_date) - MIN(M.create_date)) AS duration,
EXTRACT('epoch' FROM MIN(MO.create_date) - MIN(M.create_date)) AS time_to_answer
FROM mail_channel C
- JOIN mail_message_mail_channel_rel R ON R.mail_channel_id = C.id
- JOIN mail_message M ON R.mail_message_id = M.id
- LEFT JOIN mail_message MO ON (R.mail_message_id = MO.id AND MO.author_id = C.livechat_operator_id)
+ JOIN mail_message M ON M.res_id = C.id AND M.model = 'mail.channel'
+ LEFT JOIN mail_message MO ON (MO.res_id = C.id AND M.model = 'mail.channel' AND MO.author_id = C.livechat_operator_id)
WHERE C.livechat_channel_id IS NOT NULL
GROUP BY C.id, C.livechat_operator_id
)
diff --git a/addons/im_livechat/static/src/components/discuss/discuss_tests.js b/addons/im_livechat/static/src/components/discuss/discuss_tests.js
index 4cfd207ff1c..36c38f6180a 100644
--- a/addons/im_livechat/static/src/components/discuss/discuss_tests.js
+++ b/addons/im_livechat/static/src/components/discuss/discuss_tests.js
@@ -264,8 +264,8 @@ QUnit.test('livechats are sorted by last message date in the sidebar: most recen
assert.expect(7);
this.data['mail.message'].records.push(
- { id: 11, channel_ids: [11] }, // least recent message due to smaller id
- { id: 12, channel_ids: [12] }, // most recent message due to higher id
+ { id: 11, model: "mail.channel", res_id: 11 }, // least recent message due to smaller id
+ { id: 12, model: "mail.channel", res_id: 12 }, // most recent message due to higher id
);
this.data['mail.channel'].records.push(
{
@@ -345,7 +345,7 @@ QUnit.test('livechats with no messages are sorted by creation date in the sideba
assert.expect(5);
this.data['mail.message'].records.push(
- { id: 13, channel_ids: [13] },
+ { id: 13, model: "mail.channel", res_id: 13 },
);
this.data['mail.channel'].records.push(
{
diff --git a/addons/im_livechat/static/src/legacy/public_livechat.js b/addons/im_livechat/static/src/legacy/public_livechat.js
index 951ebb9ca45..0d3fc1eac08 100644
--- a/addons/im_livechat/static/src/legacy/public_livechat.js
+++ b/addons/im_livechat/static/src/legacy/public_livechat.js
@@ -383,8 +383,9 @@ var LivechatButton = Widget.extend({
attachment_ids: [],
author_id: this._livechat.getOperatorPID(),
body: this.options.default_message,
- channel_ids: [this._livechat.getID()],
date: time.datetime_to_str(new Date()),
+ model: "mail.channel",
+ res_id: this._livechat.getID(),
}, { prepend: true });
}
},
diff --git a/addons/im_livechat/tests/test_get_mail_channel.py b/addons/im_livechat/tests/test_get_mail_channel.py
index 30deee55d4a..fb31ab31121 100644
--- a/addons/im_livechat/tests/test_get_mail_channel.py
+++ b/addons/im_livechat/tests/test_get_mail_channel.py
@@ -87,8 +87,6 @@ class TestGetMailChannel(TransactionCase):
mail_channel = self.livechat_channel._open_livechat_mail_channel('Anonymous')
mail_channels.append(mail_channel)
# send a message to mark this channel as 'active'
- self.env['mail.channel'].browse(mail_channel['id']).write({
- 'channel_message_ids': [(0, 0, {'body': 'cc'})]
- })
+ self.env['mail.channel'].browse(mail_channel['id']).message_post(body='cc')
return mail_channels
diff --git a/addons/im_livechat/views/mail_channel_views.xml b/addons/im_livechat/views/mail_channel_views.xml
index a9e03b819b3..b3245a8e270 100644
--- a/addons/im_livechat/views/mail_channel_views.xml
+++ b/addons/im_livechat/views/mail_channel_views.xml
@@ -24,7 +24,7 @@
-
+
@@ -129,7 +129,7 @@
Sessions
mail.channel
tree,form
- [('livechat_channel_id', 'in', [active_id]), ('channel_message_ids', '!=', False)]
+ [('livechat_channel_id', 'in', [active_id]), ('message_ids', '!=', False)]
{
'search_default_livechat_channel_id': [active_id],
'default_livechat_channel_id': active_id,
diff --git a/addons/mail/data/mail_channel_data.xml b/addons/mail/data/mail_channel_data.xml
index e99f9761f4e..7a8e4b0b628 100644
--- a/addons/mail/data/mail_channel_data.xml
+++ b/addons/mail/data/mail_channel_data.xml
@@ -11,7 +11,6 @@
mail.channel
-
email
Welcome to Odoo!
diff --git a/addons/mail/data/mail_channel_demo.xml b/addons/mail/data/mail_channel_demo.xml
index a38123f80c7..5b1137089c6 100644
--- a/addons/mail/data/mail_channel_demo.xml
+++ b/addons/mail/data/mail_channel_demo.xml
@@ -23,7 +23,6 @@
Selling a training session and selling the products after the training session is more efficient than directly selling a pack with the training session and the products.
]]>
comment
-
@@ -33,7 +32,6 @@
I noted I can not manage efficiently my pipeline when I have more than 50 opportunities in the qualification stage.Any advice on this? How do you organize your activities with more than 50 opportunities?
]]>
comment
-
@@ -44,7 +42,6 @@
comment
-
@@ -53,7 +50,6 @@
mail.channel
-
Great news!
@@ -70,7 +66,6 @@
mail.channel
-
Your monthly meal vouchers arrived. You can get them at the HR's office.
This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.
]]>
comment
@@ -81,7 +76,6 @@
mail.channel
-
Thanks! Could you please remind me where is Christine's office, if I may ask? I'm new here!]]>
comment
@@ -92,7 +86,6 @@
mail.channel
-
Building B3, second floor on the right :-).]]>
comment
@@ -158,7 +151,6 @@
]]>
comment
-
diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py
index 521661a48c0..00f7b5de214 100644
--- a/addons/mail/models/mail_channel.py
+++ b/addons/mail/models/mail_channel.py
@@ -57,9 +57,6 @@ class Channel(models.Model):
channel_last_seen_partner_ids = fields.One2many(
'mail.channel.partner', 'channel_id', string='Last Seen',
groups='base.group_user')
- channel_message_ids = fields.Many2many(
- 'mail.message', 'mail_message_mail_channel_rel',
- string='Channel Messages')
is_member = fields.Boolean('Is Member', compute='_compute_is_member', compute_sudo=True)
group_ids = fields.Many2many(
'res.groups', string='Auto Subscription',
@@ -571,7 +568,6 @@ class Channel(models.Model):
# When posting a message on a mail channel, manage moderation and postpone notify users
if not msg_vals or msg_vals.get('moderation_status') != 'pending_moderation':
# link message to channel
- message.write({'channel_ids': [(4, cid) for cid in self.ids]})
rdata = super(Channel, self)._notify_thread(message, msg_vals=msg_vals, **kwargs)
message_format_values = message.message_format()[0]
@@ -871,7 +867,7 @@ class Channel(models.Model):
:rtype : list(dict)
"""
self.ensure_one()
- domain = [("channel_ids", "in", self.ids)]
+ domain = ["&", ("model", "=", "mail.channel"), ("res_id", "in", self.ids)]
if last_id:
domain.append(("id", "<", last_id))
return self.env['mail.message'].message_fetch(domain=domain, limit=limit)
@@ -990,7 +986,7 @@ class Channel(models.Model):
kept only for compatibility reasons.
"""
self.ensure_one()
- domain = [('channel_ids', 'in', self.ids)]
+ domain = ["&", ("model", "=", "mail.channel"), ("res_id", "in", self.ids)]
if last_message_id:
domain = expression.AND([domain, [('id', '<=', last_message_id)]])
last_message = self.env['mail.message'].search(domain, order="id DESC", limit=1)
@@ -1032,14 +1028,13 @@ class Channel(models.Model):
def channel_fetched(self):
""" Broadcast the channel_fetched notification to channel members
- :param channel_ids : list of channel id that has been fetched by current user
"""
for channel in self:
- if not channel.channel_message_ids.ids:
+ if not channel.message_ids.ids:
return
if channel.channel_type != 'chat':
return
- last_message_id = channel.channel_message_ids.ids[0] # zero is the index of the last message
+ last_message_id = channel.message_ids.ids[0] # zero is the index of the last message
channel_partner = self.env['mail.channel.partner'].search([('channel_id', '=', channel.id), ('partner_id', '=', self.env.user.partner_id.id)], limit=1)
if channel_partner.fetched_message_id.id == last_message_id:
# last message fetched by user is already up-to-date
@@ -1202,10 +1197,10 @@ class Channel(models.Model):
return []
self.flush()
self.env.cr.execute("""
- SELECT mail_channel_id AS id, MAX(mail_message_id) AS message_id
- FROM mail_message_mail_channel_rel
- WHERE mail_channel_id IN %s
- GROUP BY mail_channel_id
+ SELECT res_id AS id, MAX(id) AS message_id
+ FROM mail_message
+ WHERE model = 'mail.channel' AND res_id IN %s
+ GROUP BY res_id
""", (tuple(self.ids),))
return self.env.cr.dictfetchall()
@@ -1236,11 +1231,14 @@ class Channel(models.Model):
def _send_transient_message(self, partner_to, content):
""" Notifies partner_to that a message (not stored in DB) has been
written in this channel """
- self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', partner_to.id), {
- 'body': "" + content + "",
- 'channel_ids': [self.id],
- 'info': 'transient_message',
- })
+ self.env['bus.bus'].sendone(
+ (self._cr.dbname, 'res.partner', partner_to.id),
+ {'body': "" + content + "",
+ 'info': 'transient_message',
+ 'model': self._name,
+ 'res_id': self.id,
+ }
+ )
def _define_command_help(self):
return {'help': _("Show a helper message")}
diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py
index b9dd993437a..a586fd2bc3b 100644
--- a/addons/mail/models/mail_message.py
+++ b/addons/mail/models/mail_message.py
@@ -138,8 +138,6 @@ class Message(models.Model):
has_error = fields.Boolean(
'Has error', compute='_compute_has_error', search='_search_has_error',
help='Has error')
- channel_ids = fields.Many2many(
- 'mail.channel', 'mail_message_mail_channel_rel', string='Channels')
# notifications
notification_ids = fields.One2many(
'mail.notification', 'mail_message_id', 'Notifications',
@@ -292,47 +290,35 @@ class Message(models.Model):
return ids
pid = self.env.user.partner_id.id
- author_ids, partner_ids, channel_ids, allowed_ids = set([]), set([]), set([]), set([])
+ author_ids, partner_ids, allowed_ids = set([]), set([]), set([])
model_ids = {}
# check read access rights before checking the actual rules on the given ids
super(Message, self.with_user(access_rights_uid or self._uid)).check_access_rights('read')
- self.flush(['model', 'res_id', 'author_id', 'message_type', 'partner_ids', 'channel_ids'])
+ self.flush(['model', 'res_id', 'author_id', 'message_type', 'partner_ids'])
self.env['mail.notification'].flush(['mail_message_id', 'res_partner_id'])
- self.env['mail.channel'].flush(['channel_message_ids'])
- self.env['mail.channel.partner'].flush(['channel_id', 'partner_id'])
for sub_ids in self._cr.split_for_in_conditions(ids):
self._cr.execute("""
SELECT DISTINCT m.id, m.model, m.res_id, m.author_id, m.message_type,
- COALESCE(partner_rel.res_partner_id, needaction_rel.res_partner_id),
- channel_partner.channel_id as channel_id
+ COALESCE(partner_rel.res_partner_id, needaction_rel.res_partner_id)
FROM "%s" m
LEFT JOIN "mail_message_res_partner_rel" partner_rel
ON partner_rel.mail_message_id = m.id AND partner_rel.res_partner_id = %%(pid)s
LEFT JOIN "mail_notification" needaction_rel
ON needaction_rel.mail_message_id = m.id AND needaction_rel.res_partner_id = %%(pid)s
- LEFT JOIN "mail_message_mail_channel_rel" channel_rel
- ON channel_rel.mail_message_id = m.id
- LEFT JOIN "mail_channel" channel
- ON channel.id = channel_rel.mail_channel_id
- LEFT JOIN "mail_channel_partner" channel_partner
- ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = %%(pid)s
-
WHERE m.id = ANY (%%(ids)s)""" % self._table, dict(pid=pid, ids=list(sub_ids)))
- for id, rmod, rid, author_id, message_type, partner_id, channel_id in self._cr.fetchall():
+ for msg_id, rmod, rid, author_id, message_type, partner_id in self._cr.fetchall():
if author_id == pid:
- author_ids.add(id)
+ author_ids.add(msg_id)
elif partner_id == pid:
- partner_ids.add(id)
- elif channel_id:
- channel_ids.add(id)
+ partner_ids.add(msg_id)
elif rmod and rid and message_type != 'user_notification':
- model_ids.setdefault(rmod, {}).setdefault(rid, set()).add(id)
+ model_ids.setdefault(rmod, {}).setdefault(rid, set()).add(msg_id)
allowed_ids = self._find_allowed_doc_ids(model_ids)
- final_ids = author_ids | partner_ids | channel_ids | allowed_ids
+ final_ids = author_ids | partner_ids | allowed_ids
if count:
return len(final_ids)
@@ -363,7 +349,6 @@ class Message(models.Model):
- author_id == pid, uid is the author OR
- uid is in the recipients (partner_ids) OR
- uid has been notified (needaction) OR
- - uid is member of a listern channel (channel_ids.partner_ids) OR
- uid have read access to the related document if model, res_id
- otherwise: raise
- create: if
@@ -417,31 +402,24 @@ class Message(models.Model):
# Read mail_message.ids to have their values
message_values = dict((message_id, {}) for message_id in self.ids)
- self.flush(['model', 'res_id', 'author_id', 'parent_id', 'moderation_status', 'message_type', 'partner_ids', 'channel_ids'])
+ self.flush(['model', 'res_id', 'author_id', 'parent_id', 'moderation_status', 'message_type', 'partner_ids'])
self.env['mail.notification'].flush(['mail_message_id', 'res_partner_id'])
- self.env['mail.channel'].flush(['channel_message_ids', 'moderator_ids'])
- self.env['mail.channel.partner'].flush(['channel_id', 'partner_id'])
+ self.env['mail.channel'].flush(['moderator_ids'])
self.env['res.users'].flush(['moderation_channel_ids'])
if operation == 'read':
self._cr.execute("""
SELECT DISTINCT m.id, m.model, m.res_id, m.author_id, m.parent_id,
COALESCE(partner_rel.res_partner_id, needaction_rel.res_partner_id),
- channel_partner.channel_id as channel_id, m.moderation_status,
+ m.moderation_status,
m.message_type as message_type
FROM "%s" m
LEFT JOIN "mail_message_res_partner_rel" partner_rel
ON partner_rel.mail_message_id = m.id AND partner_rel.res_partner_id = %%(pid)s
LEFT JOIN "mail_notification" needaction_rel
ON needaction_rel.mail_message_id = m.id AND needaction_rel.res_partner_id = %%(pid)s
- LEFT JOIN "mail_message_mail_channel_rel" channel_rel
- ON channel_rel.mail_message_id = m.id
- LEFT JOIN "mail_channel" channel
- ON channel.id = channel_rel.mail_channel_id
- LEFT JOIN "mail_channel_partner" channel_partner
- ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = %%(pid)s
WHERE m.id = ANY (%%(ids)s)""" % self._table, dict(pid=self.env.user.partner_id.id, ids=self.ids))
- for mid, rmod, rid, author_id, parent_id, partner_id, channel_id, moderation_status, message_type in self._cr.fetchall():
+ for mid, rmod, rid, author_id, parent_id, partner_id, moderation_status, message_type in self._cr.fetchall():
message_values[mid] = {
'model': rmod,
'res_id': rid,
@@ -449,32 +427,26 @@ class Message(models.Model):
'parent_id': parent_id,
'moderation_status': moderation_status,
'moderator_id': False,
- 'notified': any((message_values[mid].get('notified'), partner_id, channel_id)),
+ 'notified': any((message_values[mid].get('notified'), partner_id)),
'message_type': message_type,
}
elif operation == 'write':
self._cr.execute("""
SELECT DISTINCT m.id, m.model, m.res_id, m.author_id, m.parent_id, m.moderation_status,
COALESCE(partner_rel.res_partner_id, needaction_rel.res_partner_id),
- channel_partner.channel_id as channel_id, channel_moderator_rel.res_users_id as moderator_id,
+ channel_moderator_rel.res_users_id as moderator_id,
m.message_type as message_type
FROM "%s" m
LEFT JOIN "mail_message_res_partner_rel" partner_rel
ON partner_rel.mail_message_id = m.id AND partner_rel.res_partner_id = %%(pid)s
LEFT JOIN "mail_notification" needaction_rel
ON needaction_rel.mail_message_id = m.id AND needaction_rel.res_partner_id = %%(pid)s
- LEFT JOIN "mail_message_mail_channel_rel" channel_rel
- ON channel_rel.mail_message_id = m.id
- LEFT JOIN "mail_channel" channel
- ON channel.id = channel_rel.mail_channel_id
- LEFT JOIN "mail_channel_partner" channel_partner
- ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = %%(pid)s
LEFT JOIN "mail_channel" moderated_channel
ON m.moderation_status = 'pending_moderation' AND m.res_id = moderated_channel.id
LEFT JOIN "mail_channel_moderator_rel" channel_moderator_rel
ON channel_moderator_rel.mail_channel_id = moderated_channel.id AND channel_moderator_rel.res_users_id = %%(uid)s
WHERE m.id = ANY (%%(ids)s)""" % self._table, dict(pid=self.env.user.partner_id.id, uid=self.env.user.id, ids=self.ids))
- for mid, rmod, rid, author_id, parent_id, moderation_status, partner_id, channel_id, moderator_id, message_type in self._cr.fetchall():
+ for mid, rmod, rid, author_id, parent_id, moderation_status, partner_id, moderator_id, message_type in self._cr.fetchall():
message_values[mid] = {
'model': rmod,
'res_id': rid,
@@ -482,7 +454,7 @@ class Message(models.Model):
'parent_id': parent_id,
'moderation_status': moderation_status,
'moderator_id': moderator_id,
- 'notified': any((message_values[mid].get('notified'), partner_id, channel_id)),
+ 'notified': any((message_values[mid].get('notified'), partner_id)),
'message_type': message_type,
}
elif operation == 'create':
@@ -583,17 +555,11 @@ class Message(models.Model):
# TDE: probably clean me
parent_ids = [message.get('parent_id') for message in message_values.values()
if message.get('parent_id')]
- self._cr.execute("""SELECT DISTINCT m.id, partner_rel.res_partner_id, channel_partner.partner_id FROM "%s" m
+ self._cr.execute("""SELECT DISTINCT m.id, partner_rel.res_partner_id FROM "%s" m
LEFT JOIN "mail_message_res_partner_rel" partner_rel
ON partner_rel.mail_message_id = m.id AND partner_rel.res_partner_id = (%%s)
- LEFT JOIN "mail_message_mail_channel_rel" channel_rel
- ON channel_rel.mail_message_id = m.id
- LEFT JOIN "mail_channel" channel
- ON channel.id = channel_rel.mail_channel_id
- LEFT JOIN "mail_channel_partner" channel_partner
- ON channel_partner.channel_id = channel.id AND channel_partner.partner_id = (%%s)
- WHERE m.id = ANY (%%s)""" % self._table, (self.env.user.partner_id.id, self.env.user.partner_id.id, parent_ids,))
- not_parent_ids = [mid[0] for mid in self._cr.fetchall() if any([mid[1], mid[2]])]
+ WHERE m.id = ANY (%%s)""" % self._table, (self.env.user.partner_id.id, parent_ids,))
+ not_parent_ids = [mid[0] for mid in self._cr.fetchall() if mid[1]]
notified_ids += [mid for mid, message in message_values.items()
if message.get('parent_id') in not_parent_ids]
@@ -774,30 +740,16 @@ class Message(models.Model):
if not notifications:
return
- # notifies changes in messages through the bus. To minimize the number of
- # notifications, we need to group the messages depending on their channel_ids
- groups = []
- messages = notifications.mapped('mail_message_id')
- current_channel_ids = messages[0].channel_ids
- current_group = []
- for record in messages:
- if record.channel_ids == current_channel_ids:
- current_group.append(record.id)
- else:
- groups.append((current_group, current_channel_ids))
- current_group = [record.id]
- current_channel_ids = record.channel_ids
-
- groups.append((current_group, current_channel_ids))
- current_group = [record.id]
- current_channel_ids = record.channel_ids
-
notifications.write({'is_read': True})
- for (msg_ids, channel_ids) in groups:
- # channel_ids in result is deprecated and will be removed in a future version
- notification = {'type': 'mark_as_read', 'message_ids': msg_ids, 'channel_ids': [c.id for c in channel_ids], 'needaction_inbox_counter': self.env.user.partner_id.get_needaction_count()}
- self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', partner_id.id), notification)
+ # notifies changes in messages through the bus.
+ self.env['bus.bus'].sendone(
+ (self._cr.dbname, 'res.partner', partner_id.id),
+ {'type': 'mark_as_read',
+ 'message_ids': notifications.mapped('mail_message_id').ids,
+ 'needaction_inbox_counter': self.env.user.partner_id.get_needaction_count()
+ }
+ )
@api.model
def unstar_all(self):
@@ -1127,7 +1079,6 @@ class Message(models.Model):
'author_id': (3, u'Administrator'),
'email_from': 'sacha@pokemon.com' # email address or False
'subtype_id': (1, u'Discussions'),
- 'channel_ids': [], # list of channel ids
'date': '2015-06-30 08:22:33',
'partner_ids': [[7, "Sacha Du Bourg-Palette"]], # list of partner name_get
'message_type': u'comment',
@@ -1164,7 +1115,7 @@ class Message(models.Model):
'id', 'body', 'date', 'author_id', 'email_from', # base message fields
'message_type', 'subtype_id', 'subject', # message specific
'model', 'res_id', 'record_name', # document related
- 'channel_ids', 'partner_ids', # recipients
+ 'partner_ids', # recipients
'starred_partner_ids', # list of partner ids for whom the message is starred
'moderation_status',
]
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 35afe3d737e..43447fa1902 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -160,10 +160,8 @@ class MailThread(models.AbstractModel):
if self.ids:
# search for unread messages, directly in SQL to improve performances
self._cr.execute(""" SELECT msg.res_id FROM mail_message msg
- RIGHT JOIN mail_message_mail_channel_rel rel
- ON rel.mail_message_id = msg.id
RIGHT JOIN mail_channel_partner cp
- ON (cp.channel_id = rel.mail_channel_id AND cp.partner_id = %s AND
+ ON (cp.channel_id = msg.res_id AND cp.partner_id = %s AND
(cp.seen_message_id IS NULL OR cp.seen_message_id < msg.id))
WHERE msg.model = %s AND msg.res_id = ANY(%s) AND
msg.message_type != 'user_notification' AND
diff --git a/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js b/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js
index 0ca449a2828..d336f17235d 100644
--- a/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js
+++ b/addons/mail/static/src/components/chat_window_manager/chat_window_manager_tests.js
@@ -1013,7 +1013,8 @@ QUnit.test('[technical] chat window: scroll conservation on toggle home menu', a
for (let i = 0; i < 10; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
}
await this.start();
@@ -1784,7 +1785,8 @@ QUnit.test('chat window with a thread: keep scroll position in message list on f
for (let i = 0; i < 10; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
}
await this.start();
@@ -1866,7 +1868,8 @@ QUnit.test('chat window should scroll to the newly posted message just after pos
for (let i = 0; i < 10; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
}
await this.start();
@@ -2023,7 +2026,8 @@ QUnit.test('[technical] chat window with a thread: keep scroll position in messa
for (let i = 0; i < 10; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
}
await this.start();
@@ -2121,7 +2125,7 @@ QUnit.test('chat window does not fetch messages if hidden', async function (asse
* 2 visible chat windows + hidden menu:
* 10 + 325 + 5 + 325 + 10 + 200 + 5 = 875 < 900
*/
- assert.expect(14);
+ assert.expect(17);
// 3 channels are expected to be found in the messaging menu, each with a
// random unique id that will be referenced in the test
@@ -2153,10 +2157,13 @@ QUnit.test('chat window does not fetch messages if hidden', async function (asse
},
mockRPC(route, args) {
if (args.method === 'message_fetch') {
- // domain should be like [['channel_id', 'in', [X]]] with X the channel id
- const channel_ids = args.kwargs.domain[0][2];
- assert.strictEqual(channel_ids.length, 1, "messages should be fetched channel per channel");
- assert.step(`rpc:message_fetch:${channel_ids[0]}`);
+ // domain should be like [['message_type', '=', 'user_notification'], ['model', '=', 'mail.channel'], ['res_id', '=', X]] with X the channel id
+ const channel_model = args.kwargs.domain[1][2];
+ const channel_id_field = args.kwargs.domain[2][0];
+ const channel_id = args.kwargs.domain[2][2];
+ assert.strictEqual(channel_model, "mail.channel", "messages should be on channel thread model");
+ assert.strictEqual(channel_id_field, "res_id", "messages should be fetched channel per channel using res_id field");
+ assert.step(`rpc:message_fetch:${channel_id}`);
}
return this._super(...arguments);
},
@@ -2243,7 +2250,6 @@ QUnit.test('new message separator is shown in a chat window of a chat on receivi
];
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [10],
model: 'mail.channel',
res_id: 10,
});
@@ -2348,7 +2354,6 @@ QUnit.test('focusing a chat window of a chat should make new message separator d
);
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [10],
model: 'mail.channel',
res_id: 10,
});
diff --git a/addons/mail/static/src/components/discuss/tests/discuss_domain_tests.js b/addons/mail/static/src/components/discuss/tests/discuss_domain_tests.js
index 26431207467..92c2280a245 100644
--- a/addons/mail/static/src/components/discuss/tests/discuss_domain_tests.js
+++ b/addons/mail/static/src/components/discuss/tests/discuss_domain_tests.js
@@ -82,10 +82,12 @@ QUnit.test('discuss should keep filter domain on changing thread', async functio
this.data['mail.channel'].records.push({ id: 20 });
this.data['mail.message'].records.push({
body: "test",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
}, {
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
await this.start();
const channel = this.env.models['mail.thread'].findFromIdentifyingData({
diff --git a/addons/mail/static/src/components/discuss/tests/discuss_inbox_tests.js b/addons/mail/static/src/components/discuss/tests/discuss_inbox_tests.js
index 63b524eb81b..2ebbd13b53b 100644
--- a/addons/mail/static/src/components/discuss/tests/discuss_inbox_tests.js
+++ b/addons/mail/static/src/components/discuss/tests/discuss_inbox_tests.js
@@ -555,7 +555,6 @@ QUnit.test('subject should not be shown when subject is the same as the thread n
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
@@ -579,7 +578,6 @@ QUnit.test('subject should not be shown when subject is the same as the thread n
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
@@ -603,7 +601,6 @@ QUnit.test('subject should not be shown when subject differs from thread name on
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
@@ -627,7 +624,6 @@ QUnit.test('subject should not be shown when subject differs from thread name on
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
@@ -651,7 +647,6 @@ QUnit.test('subject should be shown when the thread name has an extra prefix com
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
@@ -675,7 +670,6 @@ QUnit.test('subject should not be shown when subject differs from thread name on
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
@@ -699,7 +693,6 @@ QUnit.test('subject should not be shown when subject differs from thread name on
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
needaction: true,
diff --git a/addons/mail/static/src/components/discuss/tests/discuss_moderation_tests.js b/addons/mail/static/src/components/discuss/tests/discuss_moderation_tests.js
index c4c53cb568e..fc29d5ff331 100644
--- a/addons/mail/static/src/components/discuss/tests/discuss_moderation_tests.js
+++ b/addons/mail/static/src/components/discuss/tests/discuss_moderation_tests.js
@@ -988,7 +988,6 @@ QUnit.test('as moderator, new pending moderation message posted by someone else'
const messageData = {
author_id: [10, 'john doe'], // random id, different than current partner
body: "not empty",
- channel_ids: [], // server do NOT return channel_id of the message if pending moderation
id: 1, // random unique id
model: 'mail.channel', // expected value to link message to channel
moderation_status: 'pending_moderation', // message is expected to be pending
diff --git a/addons/mail/static/src/components/discuss/tests/discuss_tests.js b/addons/mail/static/src/components/discuss/tests/discuss_tests.js
index dc2005e5ac7..2a02984bb61 100644
--- a/addons/mail/static/src/components/discuss/tests/discuss_tests.js
+++ b/addons/mail/static/src/components/discuss/tests/discuss_tests.js
@@ -520,8 +520,9 @@ QUnit.test('sidebar: channel rendering with needaction counter', async function
// expected needaction message
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20], // link message to channel
id: 100, // random unique id, useful to link notification
+ model: "mail.channel",
+ res_id: 20,
});
// expected needaction notification
this.data['mail.notification'].records.push({
@@ -1194,7 +1195,6 @@ QUnit.test('load single message from channel initially', async function (assert)
this.data['mail.channel'].records.push({ id: 20 });
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
date: "2019-04-20 10:00:00",
id: 100,
model: 'mail.channel',
@@ -1215,7 +1215,11 @@ QUnit.test('load single message from channel initially', async function (assert)
);
assert.deepEqual(
args.kwargs.domain,
- [["channel_ids", "in", [20]]],
+ [
+ ["message_type", "!=", "user_notification"],
+ ["model", "=", "mail.channel"],
+ ["res_id", "=", 20]
+ ],
"should fetch messages from channel"
);
}
@@ -1288,7 +1292,6 @@ QUnit.test('basic rendering of message', async function (assert) {
this.data['mail.message'].records.push({
author_id: 11,
body: "body
",
- channel_ids: [20],
date: "2019-04-20 10:00:00",
id: 100,
model: 'mail.channel',
@@ -1390,7 +1393,6 @@ QUnit.test('basic rendering of squashed message', async function (assert) {
{
author_id: 11, // must be same author as other message
body: "body1
", // random body, set for consistency
- channel_ids: [20], // to link message to channel
date: "2019-04-20 10:00:00", // date must be within 1 min from other message
id: 100, // random unique id, will be referenced in the test
message_type: 'comment', // must be a squash-able type-
@@ -1400,7 +1402,6 @@ QUnit.test('basic rendering of squashed message', async function (assert) {
{
author_id: 11, // must be same author as other message
body: "body2
", // random body, will be asserted in the test
- channel_ids: [20], // to link message to channel
date: "2019-04-20 10:00:30", // date must be within 1 min from other message
id: 101, // random unique id, will be referenced in the test
message_type: 'comment', // must be a squash-able type
@@ -1498,7 +1499,6 @@ QUnit.test('inbox messages are never squashed', async function (assert) {
{
author_id: 11, // must be same author as other message
body: "body1
", // random body, set for consistency
- channel_ids: [20], // to link message to channel
date: "2019-04-20 10:00:00", // date must be within 1 min from other message
id: 100, // random unique id, will be referenced in the test
message_type: 'comment', // must be a squash-able type-
@@ -1510,7 +1510,6 @@ QUnit.test('inbox messages are never squashed', async function (assert) {
{
author_id: 11, // must be same author as other message
body: "body2
", // random body, will be asserted in the test
- channel_ids: [20], // to link message to channel
date: "2019-04-20 10:00:30", // date must be within 1 min from other message
id: 101, // random unique id, will be referenced in the test
message_type: 'comment', // must be a squash-able type
@@ -1563,7 +1562,6 @@ QUnit.test('load all messages from channel initially, less than fetch limit (29
for (let i = 28; i >= 0; i--) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
date: "2019-04-20 10:00:00",
model: 'mail.channel',
res_id: 20,
@@ -1623,7 +1621,6 @@ QUnit.test('load more messages from channel', async function (assert) {
for (let i = 0; i < 40; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
date: "2019-04-20 10:00:00",
model: 'mail.channel',
res_id: 20,
@@ -1695,7 +1692,6 @@ QUnit.test('auto-scroll to bottom of thread', async function (assert) {
for (let i = 1; i <= 25; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
model: 'mail.channel',
res_id: 20,
});
@@ -1743,7 +1739,6 @@ QUnit.test('load more messages from channel (auto-load on scroll)', async functi
for (let i = 0; i < 40; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
model: 'mail.channel',
res_id: 20,
});
@@ -1831,7 +1826,6 @@ QUnit.test('new messages separator [REQUIRE FOCUS]', async function (assert) {
for (let i = 1; i <= 25; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
id: 100 + i, // for setting proper value for seen_message_id
model: 'mail.channel',
res_id: 20,
@@ -1956,7 +1950,6 @@ QUnit.test('restore thread scroll position', async function (assert) {
for (let i = 1; i <= 25; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [11],
model: 'mail.channel',
res_id: 11,
});
@@ -1964,7 +1957,6 @@ QUnit.test('restore thread scroll position', async function (assert) {
for (let i = 1; i <= 24; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [12],
model: 'mail.channel',
res_id: 12,
});
@@ -2114,200 +2106,6 @@ QUnit.test('restore thread scroll position', async function (assert) {
);
});
-QUnit.test('message origin redirect to channel', async function (assert) {
- assert.expect(15);
-
- // channels expected to be rendered, with random unique id that will be referenced in the test
- this.data['mail.channel'].records.push({ id: 11 }, { id: 12 });
- this.data['mail.message'].records.push(
- {
- body: "not empty",
- channel_ids: [11, 12],
- id: 100,
- model: 'mail.channel',
- record_name: "channel11",
- res_id: 11,
- },
- {
- body: "not empty",
- channel_ids: [11, 12],
- id: 101,
- model: 'mail.channel',
- record_name: "channel12",
- res_id: 12,
- }
- );
- await this.start({
- discuss: {
- params: {
- default_active_id: 'mail.channel_11',
- },
- },
- });
- assert.strictEqual(
- document.querySelectorAll('.o_Discuss_thread .o_Message').length,
- 2,
- "should have 2 messages"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 100 }).localId
- }"]
- `).length,
- 1,
- "should have message1 (Id 100)"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- `).length,
- 1,
- "should have message2 (Id 101)"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 100 }).localId
- }"]
- .o_Message_originThread
- `).length,
- 0,
- "message1 should not have origin part in channel11 (same origin as channel)"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- .o_Message_originThread
- `).length,
- 1,
- "message2 should have origin part (origin is channel12 !== channel11)"
- );
- assert.strictEqual(
- document.querySelector(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- .o_Message_originThread
- `).textContent.trim(),
- "(from #channel12)",
- "message2 should display name of origin channel"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- .o_Message_originThreadLink
- `).length,
- 1,
- "message2 should have link to redirect to origin"
- );
-
- // click on origin link of message2 (= channel12)
- await afterNextRender(() =>
- document.querySelector(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- .o_Message_originThreadLink
- `).click()
- );
- assert.ok(
- document.querySelector(`
- .o_DiscussSidebar_groupChannel
- .o_DiscussSidebar_item[data-thread-local-id="${
- this.env.models['mail.thread'].findFromIdentifyingData({
- id: 12,
- model: 'mail.channel',
- }).localId
- }"]
- .o_DiscussSidebarItem_activeIndicator
- `).classList.contains('o-item-active'),
- "channel12 should be active channel on redirect from discuss app"
- );
- assert.strictEqual(
- document.querySelectorAll(`.o_Discuss_thread .o_Message`).length,
- 2,
- "should have 2 messages"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 100 }).localId
- }"]
- `).length,
- 1,
- "should have message1 (Id 100)"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- `).length,
- 1,
- "should have message2 (Id 101)"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 100 }).localId
- }"]
- .o_Message_originThread
- `).length,
- 1,
- "message1 should have origin thread part (= channel11 !== channel12)"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 101 }).localId
- }"]
- .o_Message_originThread
- `).length,
- 0,
- "message2 should not have origin thread part in channel12 (same as current channel)"
- );
- assert.strictEqual(
- document.querySelector(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 100 }).localId
- }"]
- .o_Message_originThread
- `).textContent.trim(),
- "(from #channel11)",
- "message1 should display name of origin channel"
- );
- assert.strictEqual(
- document.querySelectorAll(`
- .o_Discuss_thread
- .o_Message[data-message-local-id="${
- this.env.models['mail.message'].findFromIdentifyingData({ id: 100 }).localId
- }"]
- .o_Message_originThreadLink
- `).length,
- 1,
- "message1 should have link to redirect to origin channel"
- );
-});
-
QUnit.test('redirect to author (open chat)', async function (assert) {
assert.expect(7);
@@ -2333,7 +2131,6 @@ QUnit.test('redirect to author (open chat)', async function (assert) {
{
author_id: 7,
body: "not empty",
- channel_ids: [1],
id: 100,
model: 'mail.channel',
res_id: 1,
@@ -2572,7 +2369,6 @@ QUnit.test('inbox: mark all messages as read', async function (assert) {
// first expected message
{
body: "not empty",
- channel_ids: [20], // link message to channel
id: 100, // random unique id, useful to link notification
model: 'mail.channel',
// needaction needs to be set here for message_fetch domain, because
@@ -2583,7 +2379,6 @@ QUnit.test('inbox: mark all messages as read', async function (assert) {
// second expected message
{
body: "not empty",
- channel_ids: [20], // link message to channel
id: 101, // random unique id, useful to link notification
model: 'mail.channel',
// needaction needs to be set here for message_fetch domain, because
@@ -2742,7 +2537,6 @@ QUnit.test('toggle_star message', async function (assert) {
this.data['mail.channel'].records.push({ id: 20 });
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
id: 100,
model: 'mail.channel',
res_id: 20,
@@ -3326,7 +3120,6 @@ QUnit.test('mark channel as seen on last message visible [REQUIRE FOCUS]', async
this.data['mail.message'].records.push({
id: 12,
body: "not empty",
- channel_ids: [10],
model: 'mail.channel',
res_id: 10,
});
@@ -3645,7 +3438,6 @@ QUnit.test('load recent messages from thread (already loaded some old messages)'
for (let i = 0; i < 50; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20], // id of related channel
id: 100 + i, // random unique id, will be referenced in the test
model: 'mail.channel', // expected value to link message to channel
// needaction needs to be set here for message_fetch domain, because
@@ -4105,7 +3897,6 @@ QUnit.test('receive new chat message: out of odoo focus (notification, channel)'
// simulate receiving a new message with odoo focused
await afterNextRender(() => {
const messageData = {
- channel_ids: [20],
id: 126,
model: 'mail.channel',
res_id: 20,
@@ -4144,7 +3935,6 @@ QUnit.test('receive new chat message: out of odoo focus (notification, chat)', a
// simulate receiving a new message with odoo focused
await afterNextRender(() => {
const messageData = {
- channel_ids: [10],
id: 126,
model: 'mail.channel',
res_id: 10,
@@ -4196,7 +3986,6 @@ QUnit.test('receive new chat messages: out of odoo focus (tab title)', async fun
// simulate receiving a new message in chat 20 with odoo focused
await afterNextRender(() => {
const messageData1 = {
- channel_ids: [20],
id: 126,
model: 'mail.channel',
res_id: 20,
@@ -4209,7 +3998,6 @@ QUnit.test('receive new chat messages: out of odoo focus (tab title)', async fun
// simulate receiving a new message in chat 10 with odoo focused
await afterNextRender(() => {
const messageData2 = {
- channel_ids: [10],
id: 127,
model: 'mail.channel',
res_id: 10,
@@ -4222,7 +4010,6 @@ QUnit.test('receive new chat messages: out of odoo focus (tab title)', async fun
// simulate receiving another new message in chat 10 with odoo focused
await afterNextRender(() => {
const messageData3 = {
- channel_ids: [10],
id: 128,
model: 'mail.channel',
res_id: 10,
@@ -4355,12 +4142,14 @@ QUnit.test('mark channel as seen if last message is visible when switching chann
);
this.data['mail.message'].records.push({
body: 'oldest message',
- channel_ids: [10],
id: 10,
+ model: "mail.channel",
+ res_id: 10,
}, {
body: 'newest message',
- channel_ids: [11],
id: 11,
+ model: "mail.channel",
+ res_id: 11,
});
await this.start({
discuss: {
diff --git a/addons/mail/static/src/components/messaging_menu/messaging_menu_tests.js b/addons/mail/static/src/components/messaging_menu/messaging_menu_tests.js
index d049ab7a5b3..af66bbba236 100644
--- a/addons/mail/static/src/components/messaging_menu/messaging_menu_tests.js
+++ b/addons/mail/static/src/components/messaging_menu/messaging_menu_tests.js
@@ -504,7 +504,6 @@ QUnit.test('channel preview: basic rendering', async function (assert) {
this.data['mail.message'].records.push({
author_id: 7, // not current partner, will be asserted in the test
body: "test
", // random body, will be asserted in the test
- channel_ids: [20], // id of related channel
model: 'mail.channel', // necessary to link message to channel
res_id: 20, // id of related channel
});
@@ -597,12 +596,10 @@ QUnit.test('filtered previews', async function (assert) {
);
this.data['mail.message'].records.push(
{
- channel_ids: [10], // id of related channel
model: 'mail.channel', // to link message to channel
res_id: 10, // id of related channel
},
{
- channel_ids: [20], // id of related channel
model: 'mail.channel', // to link message to channel
res_id: 20, // id of related channel
},
@@ -781,7 +778,8 @@ QUnit.test('no code injection in message body preview', async function (assert)
this.data['mail.channel'].records.push({ id: 11 });
this.data['mail.message'].records.push({
body: "&shoulnotberaised
",
- channel_ids: [11],
+ model: "mail.channel",
+ res_id: 11,
});
await this.start();
@@ -822,7 +820,8 @@ QUnit.test('no code injection in message body preview from sanitized message', a
this.data['mail.channel'].records.push({ id: 11 });
this.data['mail.message'].records.push({
body: "<em>&shoulnotberaised</em><script>throw new Error('CodeInjectionError');</script>
",
- channel_ids: [11],
+ model: "mail.channel",
+ res_id: 11,
});
await this.start();
@@ -863,7 +862,8 @@ QUnit.test('
tags in message body preview are transformed in spaces', async
this.data['mail.channel'].records.push({ id: 11 });
this.data['mail.message'].records.push({
body: "a
b
c
d
",
- channel_ids: [11],
+ model: "mail.channel",
+ res_id: 11,
});
await this.start();
diff --git a/addons/mail/static/src/components/notification_list/notification_list_tests.js b/addons/mail/static/src/components/notification_list/notification_list_tests.js
index 24df5b22cdf..3cf756d4fe2 100644
--- a/addons/mail/static/src/components/notification_list/notification_list_tests.js
+++ b/addons/mail/static/src/components/notification_list/notification_list_tests.js
@@ -53,14 +53,12 @@ QUnit.test('marked as read thread notifications are ordered by last message date
);
this.data['mail.message'].records.push(
{
- channel_ids: [100],
date: "2019-01-01 00:00:00",
id: 42,
model: 'mail.channel',
res_id: 100,
},
{
- channel_ids: [200],
date: "2020-01-01 00:00:00",
id: 43,
model: 'mail.channel',
@@ -97,14 +95,12 @@ QUnit.test('thread notifications are re-ordered on receiving a new message', asy
);
this.data['mail.message'].records.push(
{
- channel_ids: [100],
date: "2019-01-01 00:00:00",
id: 42,
model: 'mail.channel',
res_id: 100,
},
{
- channel_ids: [200],
date: "2020-01-01 00:00:00",
id: 43,
model: 'mail.channel',
@@ -124,7 +120,6 @@ QUnit.test('thread notifications are re-ordered on receiving a new message', asy
const messageData = {
author_id: [7, "Demo User"],
body: "New message !
",
- channel_ids: [100],
date: "2020-03-23 10:00:00",
id: 44,
message_type: 'comment',
diff --git a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js
index ca1fe22c785..3051f318ea9 100644
--- a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js
+++ b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js
@@ -361,49 +361,6 @@ QUnit.test('preview should display last needaction message preview even if there
);
});
-QUnit.test('needaction preview should only show on its origin thread', async function (assert) {
- assert.expect(2);
-
- this.data['mail.channel'].records.push({ id: 12 });
- this.data['mail.message'].records.push({
- channel_ids: [12],
- id: 21,
- model: 'res.partner',
- needaction: true,
- needaction_partner_ids: [this.data.currentPartnerId],
- res_id: 11,
- });
- this.data['mail.notification'].records.push({
- mail_message_id: 21,
- notification_status: 'sent',
- notification_type: 'inbox',
- res_partner_id: this.data.currentPartnerId,
- });
- await this.start({ hasMessagingMenu: true });
- await afterNextRender(() => this.afterEvent({
- eventName: 'o-thread-cache-loaded-messages',
- func: () => document.querySelector('.o_MessagingMenu_toggler').click(),
- message: "should wait until inbox loaded initial needaction messages",
- predicate: ({ threadCache }) => {
- return threadCache.thread.model === 'mail.box' && threadCache.thread.id === 'inbox';
- },
- }));
- assert.containsOnce(
- document.body,
- '.o_ThreadNeedactionPreview',
- "should have only one preview"
- );
- const thread = this.env.models['mail.thread'].findFromIdentifyingData({
- id: 11,
- model: 'res.partner',
- });
- assert.containsOnce(
- document.body,
- `.o_ThreadNeedactionPreview[data-thread-local-id="${thread.localId}"]`,
- "preview should be on the origin thread"
- );
-});
-
QUnit.test('chat window header should not have unread counter for non-channel thread', async function (assert) {
assert.expect(2);
diff --git a/addons/mail/static/src/components/thread_preview/thread_preview_tests.js b/addons/mail/static/src/components/thread_preview/thread_preview_tests.js
index 981abf6bca6..bc33f7cd0f8 100644
--- a/addons/mail/static/src/components/thread_preview/thread_preview_tests.js
+++ b/addons/mail/static/src/components/thread_preview/thread_preview_tests.js
@@ -47,7 +47,6 @@ QUnit.test('mark as read', async function (assert) {
message_unread_counter: 1,
});
this.data['mail.message'].records.push({
- channel_ids: [11],
id: 100,
model: 'mail.channel',
res_id: 11,
diff --git a/addons/mail/static/src/components/thread_view/thread_view_tests.js b/addons/mail/static/src/components/thread_view/thread_view_tests.js
index 87d33c89548..a3e1f15eb1a 100644
--- a/addons/mail/static/src/components/thread_view/thread_view_tests.js
+++ b/addons/mail/static/src/components/thread_view/thread_view_tests.js
@@ -106,7 +106,6 @@ QUnit.test('message list desc order', async function (assert) {
for (let i = 0; i <= 60; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
});
@@ -204,7 +203,6 @@ QUnit.test('message list asc order', async function (assert) {
for (let i = 0; i <= 60; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
});
@@ -466,7 +464,6 @@ QUnit.test('show message subject if thread is mailing channel', async function (
});
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [100],
model: 'mail.channel',
res_id: 100,
subject: "Salutations, voyageur",
@@ -513,8 +510,9 @@ QUnit.test('[technical] new messages separator on posting message', async functi
}];
this.data['mail.message'].records.push({
body: "first message",
- channel_ids: [20],
id: 10,
+ model: "mail.channel",
+ res_id: 20,
});
await this.start();
const thread = this.env.models['mail.thread'].findFromIdentifyingData({
@@ -582,8 +580,9 @@ QUnit.test('new messages separator on receiving new message [REQUIRE FOCUS]', as
});
this.data['mail.message'].records.push({
body: "blah",
- channel_ids: [20],
id: 1,
+ model: "mail.channel",
+ res_id: 20,
});
await this.start();
const thread = this.env.models['mail.thread'].findFromIdentifyingData({
@@ -724,7 +723,6 @@ QUnit.test('basic rendering of canceled notification', async function (assert) {
this.data['res.partner'].records.push({ id: 12, name: "Someone" });
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [11],
id: 10,
message_type: 'email',
model: 'mail.channel',
@@ -825,7 +823,8 @@ QUnit.test('should scroll to bottom on receiving new message if the list is init
for (let i = 0; i <= 10; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
}
await this.start();
@@ -896,7 +895,8 @@ QUnit.test('should not scroll on receiving new message if the list is initially
for (let i = 0; i <= 10; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [20],
+ model: "mail.channel",
+ res_id: 20,
});
}
await this.start();
@@ -973,8 +973,9 @@ QUnit.test("delete all attachments of message without content should no longer d
this.data['mail.message'].records.push(
{
attachment_ids: [143],
- channel_ids: [11],
id: 101,
+ model: "mail.channel",
+ res_id: 11,
}
);
await this.start();
@@ -1031,8 +1032,9 @@ QUnit.test('delete all attachments of a message with some text content should st
{
attachment_ids: [143],
body: "Some content",
- channel_ids: [11],
id: 101,
+ model: "mail.channel",
+ res_id: 11,
},
);
await this.start();
@@ -1088,8 +1090,9 @@ QUnit.test('delete all attachments of a message with tracking fields should stil
this.data['mail.message'].records.push(
{
attachment_ids: [143],
- channel_ids: [11],
id: 101,
+ model: "mail.channel",
+ res_id: 11,
tracking_value_ids: [6]
},
);
@@ -1573,8 +1576,9 @@ QUnit.test('show empty placeholder when thread contains only empty messages', as
this.data['mail.channel'].records.push({ id: 11 });
this.data['mail.message'].records.push(
{
- channel_ids: [11],
id: 101,
+ model: "mail.channel",
+ res_id: 11,
},
);
await this.start();
@@ -1621,8 +1625,9 @@ QUnit.test('message with subtype should be displayed (and not considered as empt
});
this.data['mail.message'].records.push(
{
- channel_ids: [11],
id: 101,
+ model: "mail.channel",
+ res_id: 11,
subtype_id: 10,
},
);
@@ -1673,12 +1678,14 @@ QUnit.test('[technical] message list with a full page of empty messages should s
for (let i = 0; i <= 30; i++) {
this.data['mail.message'].records.push({
body: "not empty",
- channel_ids: [11],
+ model: "mail.channel",
+ res_id: 11,
});
}
for (let i = 0; i <= 30; i++) {
this.data['mail.message'].records.push({
- channel_ids: [11],
+ model: "mail.channel",
+ res_id: 11,
});
}
await this.start();
@@ -1900,8 +1907,9 @@ QUnit.test('failure on loading more messages should not alter message list displ
this.data['mail.message'].records.push(...[...Array(60).keys()].map(id => {
return {
body: 'coucou',
- channel_ids: [20],
id,
+ model: "mail.channel",
+ res_id: 20,
};
}));
await this.start({
@@ -1950,8 +1958,9 @@ QUnit.test('failure on loading more messages should display error and prompt ret
this.data['mail.message'].records.push(...[...Array(60).keys()].map(id => {
return {
body: 'coucou',
- channel_ids: [20],
id,
+ model: "mail.channel",
+ res_id: 20,
};
}));
await this.start({
@@ -2009,8 +2018,9 @@ QUnit.test('Retry loading more messages on failed load more messages should load
this.data['mail.message'].records = [...Array(90).keys()].map(id => {
return {
body: 'coucou',
- channel_ids: [20],
id,
+ model: "mail.channel",
+ res_id: 20,
};
});
await this.start({
diff --git a/addons/mail/static/src/models/composer/composer.js b/addons/mail/static/src/models/composer/composer.js
index 2c0813ec50c..301ec2c9967 100644
--- a/addons/mail/static/src/models/composer/composer.js
+++ b/addons/mail/static/src/models/composer/composer.js
@@ -292,7 +292,6 @@ function factory(dependencies) {
let postData = {
attachment_ids: this.attachments.map(attachment => attachment.id),
body,
- channel_ids: this.mentionedChannels.map(channel => channel.id),
message_type: 'comment',
partner_ids: this.recipients.map(partner => partner.id),
};
diff --git a/addons/mail/static/src/models/message/message.js b/addons/mail/static/src/models/message/message.js
index a3cf9f20d24..7c0fdb8cb18 100644
--- a/addons/mail/static/src/models/message/message.js
+++ b/addons/mail/static/src/models/message/message.js
@@ -63,16 +63,6 @@ function factory(dependencies) {
if ('body' in data) {
data2.body = data.body;
}
- if ('channel_ids' in data && data.channel_ids) {
- const channels = data.channel_ids
- .map(channelId =>
- this.env.models['mail.thread'].findFromIdentifyingData({
- id: channelId,
- model: 'mail.channel',
- })
- ).filter(channel => !!channel);
- data2.serverChannels = [['replace', channels]];
- }
if ('date' in data && data.date) {
data2.date = moment(str_to_datetime(data.date));
}
@@ -545,7 +535,7 @@ function factory(dependencies) {
* @returns {mail.thread[]}
*/
_computeThreads() {
- const threads = [...this.serverChannels];
+ const threads = [];
if (this.isHistory) {
threads.push(this.env.messaging.history);
}
@@ -794,20 +784,12 @@ function factory(dependencies) {
'messagingModeration',
'messagingStarred',
'originThread',
- 'serverChannels',
],
inverse: 'messages',
}),
tracking_value_ids: attr({
default: [],
}),
- /**
- * All channels containing this message on the server.
- * Equivalent of python field `channel_ids`.
- */
- serverChannels: many2many('mail.thread', {
- inverse: 'messagesAsServerChannel',
- }),
};
Message.modelName = 'mail.message';
diff --git a/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js b/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js
index dcd8b09f688..0614984b974 100644
--- a/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js
+++ b/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js
@@ -540,11 +540,10 @@ function factory(dependencies) {
/**
* @private
* @param {Object} param0
- * @param {integer[]} [param0.channel_ids
* @param {integer[]} [param0.message_ids=[]]
* @param {integer} [param0.needaction_inbox_counter]
*/
- _handleNotificationPartnerMarkAsRead({ channel_ids, message_ids = [], needaction_inbox_counter }) {
+ _handleNotificationPartnerMarkAsRead({ message_ids = [], needaction_inbox_counter }) {
for (const message_id of message_ids) {
// We need to ignore all not yet known messages because we don't want them
// to be shown partially as they would be linked directly to mainCache
diff --git a/addons/mail/static/src/models/thread/thread.js b/addons/mail/static/src/models/thread/thread.js
index 6b2c68f06ec..b02f4a2739e 100644
--- a/addons/mail/static/src/models/thread/thread.js
+++ b/addons/mail/static/src/models/thread/thread.js
@@ -139,9 +139,7 @@ function factory(dependencies) {
* @return {Object}
*/
static convertData(data) {
- const data2 = {
- messagesAsServerChannel: [],
- };
+ const data2 = {};
if ('model' in data) {
data2.model = data.model;
}
@@ -171,12 +169,20 @@ function factory(dependencies) {
data2.isServerPinned = data.is_pinned;
}
if ('last_message' in data && data.last_message) {
- data2.messagesAsServerChannel.push(['insert', { id: data.last_message.id }]);
- data2.serverLastMessageId = data.last_message.id;
+ const messageData = this.env.models['mail.message'].convertData({
+ id: data.last_message.id,
+ model: data2.model,
+ res_id: data2.id,
+ });
+ data2.serverLastMessage = [['insert', messageData]];
}
if ('last_message_id' in data && data.last_message_id) {
- data2.messagesAsServerChannel.push(['insert', { id: data.last_message_id }]);
- data2.serverLastMessageId = data.last_message_id;
+ const messageData = this.env.models['mail.message'].convertData({
+ id: data.last_message_id,
+ model: data2.model,
+ res_id: data2.id,
+ });
+ data2.serverLastMessage = [['insert', messageData]];
}
if ('mass_mailing' in data) {
data2.mass_mailing = data.mass_mailing;
@@ -1247,7 +1253,7 @@ function factory(dependencies) {
// By default trust the server up to the last message it used
// because it's not possible to do better.
let baseCounter = this.serverMessageUnreadCounter;
- let countFromId = this.serverLastMessageId;
+ let countFromId = this.serverLastMessage ? this.serverLastMessage.id : 0;
// But if the client knows the last seen message that the server
// returned (and by assumption all the messages that come after),
// the counter can be computed fully locally, ignoring potentially
@@ -1843,7 +1849,7 @@ function factory(dependencies) {
'lastSeenByCurrentPartnerMessageId',
'messagingCurrentPartner',
'orderedMessages',
- 'serverLastMessageId',
+ 'serverLastMessage',
'serverMessageUnreadCounter',
],
}),
@@ -1893,13 +1899,6 @@ function factory(dependencies) {
messagesAsOriginThreadIsNeedaction: attr({
related: 'messagesAsOriginThread.isNeedaction',
}),
- /**
- * All messages that are contained on this channel on the server.
- * Equivalent to the inverse of python field `channel_ids`.
- */
- messagesAsServerChannel: many2many('mail.message', {
- inverse: 'serverChannels',
- }),
/**
* Contains the message fetched/seen indicators for all messages of this thread.
* FIXME This field should be readonly once task-2336946 is done.
@@ -2077,15 +2076,13 @@ function factory(dependencies) {
default: 'closed',
}),
/**
- * Last message id considered by the server.
+ * Last message considered by the server.
*
* Useful to compute localMessageUnreadCounter field.
*
* @see localMessageUnreadCounter
*/
- serverLastMessageId: attr({
- default: 0,
- }),
+ serverLastMessage: many2one('mail.message'),
/**
* Message unread counter coming from server.
*
diff --git a/addons/mail/static/src/models/thread_cache/thread_cache.js b/addons/mail/static/src/models/thread_cache/thread_cache.js
index f97222307da..da0752f5f46 100644
--- a/addons/mail/static/src/models/thread_cache/thread_cache.js
+++ b/addons/mail/static/src/models/thread_cache/thread_cache.js
@@ -253,9 +253,7 @@ function factory(dependencies) {
*/
_extendMessageDomain(domain) {
const thread = this.thread;
- if (thread.model === 'mail.channel') {
- return domain.concat([['channel_ids', 'in', [thread.id]]]);
- } else if (thread === this.env.messaging.inbox) {
+ if (thread === this.env.messaging.inbox) {
return domain.concat([['needaction', '=', true]]);
} else if (thread === this.env.messaging.starred) {
return domain.concat([
diff --git a/addons/mail/static/tests/helpers/mock_models.js b/addons/mail/static/tests/helpers/mock_models.js
index 70da8ce0393..bd1a06b6ad9 100644
--- a/addons/mail/static/tests/helpers/mock_models.js
+++ b/addons/mail/static/tests/helpers/mock_models.js
@@ -125,7 +125,6 @@ class MockModels {
attachment_ids: { string: "Attachments", type: 'many2many', relation: 'ir.attachment', default: [] },
author_id: { string: "Author", type: 'many2one', relation: 'res.partner', default() { return this.currentPartnerId; } },
body: { string: "Contents", type: 'html', default: "" },
- channel_ids: { string: "Channels", type: 'many2many', relation: 'mail.channel' },
date: { string: "Date", type: 'datetime' },
email_from: { string: "From", type: 'char' },
history_partner_ids: { string: "Partners with History", type: 'many2many', relation: 'res.partner' },
diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js
index 1ce1b3c8766..c358a548e7a 100644
--- a/addons/mail/static/tests/helpers/mock_server.js
+++ b/addons/mail/static/tests/helpers/mock_server.js
@@ -598,7 +598,10 @@ MockServer.include({
_mockMailChannelChannelFetched(ids) {
const channels = this._getRecords('mail.channel', [['id', 'in', ids]]);
for (const channel of channels) {
- const channelMessages = this._getRecords('mail.message', [['channel_ids', 'in', channel.id]]);
+ const channelMessages = this._getRecords('mail.message', [
+ ['model', '=', 'mail.channel'],
+ ['res_id', '=', channel.id],
+ ]);
const lastMessage = channelMessages.reduce((lastMessage, message) => {
if (message.id > lastMessage.id) {
return message;
@@ -634,7 +637,10 @@ MockServer.include({
_mockMailChannelChannelFetchPreview(ids) {
const channels = this._getRecords('mail.channel', [['id', 'in', ids]]);
return channels.map(channel => {
- const channelMessages = this._getRecords('mail.message', [['channel_ids', 'in', channel.id]]);
+ const channelMessages = this._getRecords('mail.message', [
+ ['model', '=', 'mail.channel'],
+ ['res_id', '=', channel.id],
+ ]);
const lastMessage = channelMessages.reduce((lastMessage, message) => {
if (message.id > lastMessage.id) {
return message;
@@ -727,7 +733,8 @@ MockServer.include({
return channels.map(channel => {
const members = channel.members.map(partnerId => partnerInfos[partnerId]);
const messages = this._getRecords('mail.message', [
- ['channel_ids', 'in', [channel.id]],
+ ['model', '=', 'mail.channel'],
+ ['res_id', '=', channel.id],
]);
const lastMessageId = messages.reduce((lastMessageId, message) => {
if (!lastMessageId || message.id > lastMessageId) {
@@ -804,8 +811,9 @@ MockServer.include({
}
const channel = this._getRecords('mail.channel', [['id', '=', channel_id]])[0];
const messagesBeforeGivenLastMessage = this._getRecords('mail.message', [
- ['channel_ids', 'in', [channel.id]],
['id', '<=', last_message_id],
+ ['model', '=', 'mail.channel'],
+ ['res_id', '=', channel.id],
]);
if (!messagesBeforeGivenLastMessage || messagesBeforeGivenLastMessage.length === 0) {
return;
@@ -880,8 +888,9 @@ MockServer.include({
["dbName", 'res.partner', this.currentPartnerId],
{
'body': `${message}`,
- 'channel_ids': [channel.id],
'info': 'transient_message',
+ 'model': 'mail.channel',
+ 'res_id': channel.id,
}
];
this._widget.call('bus_service', 'trigger', 'notification', [notification]);
@@ -1267,7 +1276,7 @@ MockServer.include({
this._mockWrite('mail.message', [[message.id], {
moderation_status: 'accepted',
}]);
- this._mockMailThread_NotifyThread(model, message.channel_ids, message.id);
+ this._mockMailThread_NotifyThread(model, [message.res_id], message.id);
}
}
},
@@ -1333,9 +1342,7 @@ MockServer.include({
),
},
]);
- // NOTE server is sending grouped notifications per channel_ids but
- // this optimization is not needed here.
- const data = { type: 'mark_as_read', message_ids: [message.id], channel_ids: message.channel_ids, needaction_inbox_counter: this._mockResPartnerGetNeedactionCount() };
+ const data = { type: 'mark_as_read', message_ids: [message.id], needaction_inbox_counter: this._mockResPartnerGetNeedactionCount() };
const busNotifications = [[[false, 'res.partner', this.currentPartnerId], data]];
this._widget.call('bus_service', 'trigger', 'notification', busNotifications);
}
@@ -1636,7 +1643,7 @@ MockServer.include({
notifications.push([[false, 'res.partner', message.author_id], notificationData]);
}
// members
- const channels = this._getRecords('mail.channel', [['id', 'in', message.channel_ids]]);
+ const channels = this._getRecords('mail.channel', [['id', '=', message.res_id]]);
for (const channel of channels) {
notifications.push([[false, 'mail.channel', channel.id], messageFormat]);
}
diff --git a/addons/mail/tests/test_mail_channel.py b/addons/mail/tests/test_mail_channel.py
index e36272c1a50..2c3b138e965 100644
--- a/addons/mail/tests/test_mail_channel.py
+++ b/addons/mail/tests/test_mail_channel.py
@@ -206,7 +206,8 @@ class TestChannelInternals(MailCommon):
with self.mock_mail_gateway():
new_msg = channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertNotSentEmail()
- self.assertEqual(new_msg.channel_ids, channel)
+ self.assertEqual(new_msg.model, self.test_channel._name)
+ self.assertEqual(new_msg.res_id, self.test_channel.id)
self.assertEqual(new_msg.partner_ids, self.env['res.partner'])
self.assertEqual(new_msg.notified_partner_ids, self.env['res.partner'])
@@ -223,7 +224,8 @@ class TestChannelInternals(MailCommon):
channel = self.env['mail.channel'].browse(self.test_channel.ids)
new_msg = channel.message_post(body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
self.assertNotSentEmail()
- self.assertEqual(new_msg.channel_ids, self.test_channel)
+ self.assertEqual(new_msg.model, self.test_channel._name)
+ self.assertEqual(new_msg.res_id, self.test_channel.id)
self.assertEqual(new_msg.partner_ids, self.env['res.partner'])
self.assertEqual(new_msg.notified_partner_ids, self.env['res.partner'])
@@ -320,12 +322,8 @@ class TestChannelInternals(MailCommon):
channel.write({'channel_type': 'chat'})
channel.action_follow()
- msg_1 = self._add_messages(
- self.test_channel, 'Body1', author=self.user_employee.partner_id,
- channel_ids=[self.test_channel.id])
- msg_2 = self._add_messages(
- self.test_channel, 'Body2', author=self.user_employee.partner_id,
- channel_ids=[self.test_channel.id])
+ msg_1 = self._add_messages(self.test_channel, 'Body1', author=self.user_employee.partner_id)
+ msg_2 = self._add_messages(self.test_channel, 'Body2', author=self.user_employee.partner_id)
self.test_channel.channel_seen(msg_2.id)
self.assertEqual(
@@ -440,12 +438,10 @@ class TestChannelModeration(MailCommon):
msg_c1_emplo2 = self._add_messages(self.channel, 'Body21', author=self.partner_employee_2, moderation_status='pending_moderation')
self._reset_bus()
- self.assertFalse(msg_c1_admin1.channel_ids | msg_c1_admin2.channel_ids | msg_c1_emplo2.channel_ids)
# accept
with self.assertBus([(self.cr.dbname, 'mail.channel', self.channel.id)]):
msg_c1_admin1.with_user(self.user_employee)._moderate('accept')
- self.assertEqual(msg_c1_admin1.channel_ids, self.channel)
self.assertEqual(msg_c1_admin1.moderation_status, 'accepted')
self.assertEqual(msg_c1_admin2.moderation_status, 'pending_moderation')
@@ -455,9 +451,6 @@ class TestChannelModeration(MailCommon):
(self.cr.dbname, 'mail.channel', self.channel.id),
(self.cr.dbname, 'mail.channel', self.channel.id)]):
(msg_c1_admin1 | msg_c1_emplo2).with_user(self.user_employee)._moderate('allow')
- self.assertEqual(msg_c1_admin1.channel_ids, self.channel)
- self.assertEqual(msg_c1_admin2.channel_ids, self.channel)
- self.assertEqual(msg_c1_emplo2.channel_ids, self.channel)
self.assertEqual(msg_c1_admin1.moderation_status, 'accepted')
self.assertEqual(msg_c1_admin2.moderation_status, 'accepted')
self.assertEqual(msg_c1_emplo2.moderation_status, 'accepted')
@@ -470,8 +463,6 @@ class TestChannelModeration(MailCommon):
msg_c1_portal = self._add_messages(self.channel, 'Body12
', author=self.partner_portal, moderation_status='pending_moderation')
id2, id4 = msg_c1_admin2.id, msg_c1_portal.id # save ids because unlink will discard them
- self.assertFalse(msg_c1_admin1.channel_ids | msg_c1_admin2.channel_ids | msg_c1_emplo2.channel_ids | msg_c1_portal.channel_ids)
-
# test reject: should also send a rejection email
with self.mock_mail_gateway():
(msg_c1_admin1 | msg_c1_emplo2).with_user(self.user_employee)._moderate('reject', title='RejectTitle', comment='RejectComment')
@@ -670,5 +661,3 @@ class TestChannelModeration(MailCommon):
self.assertFalse(msg_email1)
self.assertEqual(msg_admin, pending_messages)
self.assertEqual(accepted_messages, msg_moderator | msg_email2 | msg_notif)
- self.assertFalse(msg_admin.channel_ids)
- self.assertEqual(msg_email2.channel_ids, channel)
diff --git a/addons/mail/views/mail_message_views.xml b/addons/mail/views/mail_message_views.xml
index df65876ee14..401c4131e2c 100644
--- a/addons/mail/views/mail_message_views.xml
+++ b/addons/mail/views/mail_message_views.xml
@@ -64,7 +64,6 @@
-
diff --git a/addons/test_mail/tests/test_message_post.py b/addons/test_mail/tests/test_message_post.py
index 09370bd9ade..db0c27812dd 100644
--- a/addons/test_mail/tests/test_message_post.py
+++ b/addons/test_mail/tests/test_message_post.py
@@ -128,7 +128,6 @@ class TestMessagePost(TestMailCommon, TestRecipients):
self.assertEqual(msg.body, _body)
self.assertEqual(msg.partner_ids, self.partner_1 | self.partner_2)
self.assertEqual(msg.notified_partner_ids, self.user_admin.partner_id | self.partner_1 | self.partner_2)
- self.assertEqual(msg.channel_ids, self.env['mail.channel'])
# notifications emails should have been deleted
self.assertFalse(self.env['mail.mail'].sudo().search([('mail_message_id', '=', msg.id)]),
diff --git a/addons/website_crm_livechat/models/crm_lead.py b/addons/website_crm_livechat/models/crm_lead.py
index 1b2622aa8a8..9751c5bdb97 100644
--- a/addons/website_crm_livechat/models/crm_lead.py
+++ b/addons/website_crm_livechat/models/crm_lead.py
@@ -17,5 +17,5 @@ class Lead(models.Model):
def action_redirect_to_livechat_sessions(self):
visitors = self.visitor_ids
action = self.env["ir.actions.actions"]._for_xml_id("website_livechat.website_visitor_livechat_session_action")
- action['domain'] = [('livechat_visitor_id', 'in', visitors.ids), ('channel_message_ids', '!=', False)]
+ action['domain'] = [('livechat_visitor_id', 'in', visitors.ids), ('message_ids', '!=', False)]
return action
diff --git a/addons/website_livechat/models/mail_channel.py b/addons/website_livechat/models/mail_channel.py
index 6137dcc8e23..589027a70fa 100644
--- a/addons/website_livechat/models/mail_channel.py
+++ b/addons/website_livechat/models/mail_channel.py
@@ -18,7 +18,7 @@ class MailChannel(models.Model):
delete mail_channel as not useful to keep empty chat
"""
super(MailChannel, self)._execute_channel_pin(pinned)
- if self.livechat_active and not self.channel_message_ids:
+ if self.livechat_active and not self.message_ids:
self.unlink()
def channel_info(self, extra_info=False):
diff --git a/addons/website_livechat/models/website.py b/addons/website_livechat/models/website.py
index a4bd8b1513e..95874357ecb 100644
--- a/addons/website_livechat/models/website.py
+++ b/addons/website_livechat/models/website.py
@@ -41,7 +41,7 @@ class Website(models.Model):
('livechat_visitor_id', '=', visitor.id),
('livechat_channel_id', '=', self.channel_id.id),
('livechat_active', '=', True),
- ('channel_message_ids', '!=', False)
+ ('message_ids', '!=', False)
], order='create_date desc', limit=1)
if chat_request_channel:
return {
diff --git a/addons/website_livechat/models/website_visitor.py b/addons/website_livechat/models/website_visitor.py
index a70145abeff..ef387225894 100644
--- a/addons/website_livechat/models/website_visitor.py
+++ b/addons/website_livechat/models/website_visitor.py
@@ -31,7 +31,7 @@ class WebsiteVisitor(models.Model):
def _compute_session_count(self):
sessions = self.env['mail.channel'].search([('livechat_visitor_id', 'in', self.ids)])
session_count = dict.fromkeys(self.ids, 0)
- for session in sessions.filtered(lambda c: c.channel_message_ids):
+ for session in sessions.filtered(lambda c: c.message_ids):
session_count[session.livechat_visitor_id.id] += 1
for visitor in self:
visitor.session_count = session_count.get(visitor.id, 0)
diff --git a/addons/website_livechat/views/website_visitor_views.xml b/addons/website_livechat/views/website_visitor_views.xml
index 595e7b6b5a3..1787d1fdd21 100644
--- a/addons/website_livechat/views/website_visitor_views.xml
+++ b/addons/website_livechat/views/website_visitor_views.xml
@@ -5,7 +5,7 @@
mail.channel
tree,form
- [('livechat_visitor_id', '=', active_id), ('channel_message_ids', '!=', False)]
+ [('livechat_visitor_id', '=', active_id), ('message_ids', '!=', False)]
{
'search_default_livechat_visitor_id': [active_id],
'default_livechat_visitor_id': active_id,