[REF] mail, *: rename mail.channel to discuss.channel
* = bus, calendar, crm_livechat, hr, hr_holidays, im_livechat, mail_bot,
mass_mailing, privacy_lookup, test_discuss_full, test_mail,
test_mail_full, website_crm_livechat, website_livechat, base
In preparation of splitting discuss and mail modules.
Part of task-3265211
closes odoo/odoo#118354
Related: odoo/upgrade#4553
Related: odoo/enterprise#39661
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
@@ -9,5 +9,5 @@ class TestIrWebsocket(common.HttpCase):
|
||||
self.env['ir.websocket']._subscribe({
|
||||
'inactivity_period': 1000,
|
||||
'last': 0,
|
||||
'channels': [('odoo', 'mail.channel', 5)],
|
||||
'channels': [('odoo', 'discuss.channel', 5)],
|
||||
})
|
||||
|
||||
@@ -106,7 +106,7 @@ class Meeting(models.Model):
|
||||
videocall_location = fields.Char('Meeting URL', compute='_compute_videocall_location', store=True, copy=True)
|
||||
access_token = fields.Char('Invitation Token', store=True, copy=False, index=True)
|
||||
videocall_source = fields.Selection([('discuss', 'Discuss'), ('custom', 'Custom')], compute='_compute_videocall_source')
|
||||
videocall_channel_id = fields.Many2one('mail.channel', 'Discuss Channel')
|
||||
videocall_channel_id = fields.Many2one('discuss.channel', 'Discuss Channel')
|
||||
# visibility
|
||||
privacy = fields.Selection(
|
||||
[('public', 'Public'),
|
||||
@@ -756,7 +756,7 @@ class Meeting(models.Model):
|
||||
self.videocall_channel_id.channel_change_description(self.recurrence_id.name if self.recurrency else self.display_time)
|
||||
|
||||
def _create_videocall_channel_id(self, name, partner_ids):
|
||||
videocall_channel_id = self.env['mail.channel'].create_group(partner_ids, default_display_mode='video_full_screen', name=name)
|
||||
videocall_channel_id = self.env['discuss.channel'].create_group(partner_ids, default_display_mode='video_full_screen', name=name)
|
||||
# if recurrent event, set channel to all other records of the same recurrency
|
||||
if self.recurrency:
|
||||
recurrent_events_without_channel = self.env['calendar.event'].search([
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
from . import chatbot_script
|
||||
from . import chatbot_script_step
|
||||
from . import mail_channel
|
||||
from . import discuss_channel
|
||||
|
||||
@@ -14,9 +14,9 @@ class ChatbotScriptStep(models.Model):
|
||||
help="Used in combination with 'create_lead' step type in order to automatically "
|
||||
"assign the created lead/opportunity to the defined team")
|
||||
|
||||
def _chatbot_crm_prepare_lead_values(self, mail_channel, description):
|
||||
def _chatbot_crm_prepare_lead_values(self, discuss_channel, description):
|
||||
return {
|
||||
'description': description + mail_channel._get_channel_history(),
|
||||
'description': description + discuss_channel._get_channel_history(),
|
||||
'name': _("%s's New Lead", self.chatbot_script_id.title),
|
||||
'source_id': self.chatbot_script_id.source_id.id,
|
||||
'team_id': self.crm_team_id.id,
|
||||
@@ -24,17 +24,17 @@ class ChatbotScriptStep(models.Model):
|
||||
'user_id': False,
|
||||
}
|
||||
|
||||
def _process_step(self, mail_channel):
|
||||
def _process_step(self, discuss_channel):
|
||||
self.ensure_one()
|
||||
|
||||
posted_message = super()._process_step(mail_channel)
|
||||
posted_message = super()._process_step(discuss_channel)
|
||||
|
||||
if self.step_type == 'create_lead':
|
||||
self._process_step_create_lead(mail_channel)
|
||||
self._process_step_create_lead(discuss_channel)
|
||||
|
||||
return posted_message
|
||||
|
||||
def _process_step_create_lead(self, mail_channel):
|
||||
def _process_step_create_lead(self, discuss_channel):
|
||||
""" When reaching a 'create_lead' step, we extract the relevant information: visitor's
|
||||
email, phone and conversation history to create a crm.lead.
|
||||
|
||||
@@ -46,7 +46,7 @@ class ChatbotScriptStep(models.Model):
|
||||
their interest / needs before creating the lead. """
|
||||
|
||||
customer_values = self._chatbot_prepare_customer_values(
|
||||
mail_channel, create_partner=False, update_partner=True)
|
||||
discuss_channel, create_partner=False, update_partner=True)
|
||||
if self.env.user._is_public():
|
||||
create_values = {
|
||||
'email_from': customer_values['email'],
|
||||
@@ -60,6 +60,6 @@ class ChatbotScriptStep(models.Model):
|
||||
}
|
||||
|
||||
create_values.update(self._chatbot_crm_prepare_lead_values(
|
||||
mail_channel, customer_values['description']))
|
||||
discuss_channel, customer_values['description']))
|
||||
|
||||
self.env['crm.lead'].create(create_values)
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ from odoo import models, _
|
||||
from odoo.tools import html2plaintext
|
||||
|
||||
|
||||
class MailChannel(models.Model):
|
||||
_inherit = 'mail.channel'
|
||||
class DiscussChannel(models.Model):
|
||||
_inherit = 'discuss.channel'
|
||||
|
||||
def execute_command_lead(self, **kwargs):
|
||||
partner = self.env.user.partner_id
|
||||
@@ -3,7 +3,7 @@
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("mail.channel_commands").add("lead", {
|
||||
registry.category("discuss.channel_commands").add("lead", {
|
||||
help: _lt("Create a new lead (/lead lead title)"),
|
||||
methodName: "execute_command_lead",
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ QUnit.module("composer");
|
||||
|
||||
QUnit.test("Can execute lead command", async function (assert) {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({ name: "General" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
const { openDiscuss } = await start({
|
||||
mockRPC(route, args) {
|
||||
if (args.method === "execute_command_lead") {
|
||||
|
||||
@@ -33,19 +33,19 @@ class CrmChatbotCase(chatbot_common.CrmChatbotCase):
|
||||
self.assertEqual(created_lead.type, 'lead')
|
||||
|
||||
def _chatbot_create_lead(self, user):
|
||||
channel_info = self.livechat_channel._open_livechat_mail_channel(
|
||||
channel_info = self.livechat_channel._open_livechat_discuss_channel(
|
||||
anonymous_name='Test Visitor', chatbot_script=self.chatbot_script, user_id=user.id)
|
||||
mail_channel = self.env['mail.channel'].sudo().browse(channel_info['id'])
|
||||
discuss_channel = self.env['discuss.channel'].sudo().browse(channel_info['id'])
|
||||
|
||||
self._post_answer_and_trigger_next_step(
|
||||
mail_channel,
|
||||
discuss_channel,
|
||||
self.step_dispatch_create_lead.name,
|
||||
chatbot_script_answer=self.step_dispatch_create_lead
|
||||
)
|
||||
self.assertEqual(mail_channel.chatbot_current_step_id, self.step_create_lead_email)
|
||||
self._post_answer_and_trigger_next_step(mail_channel, 'test2@example.com')
|
||||
self.assertEqual(discuss_channel.chatbot_current_step_id, self.step_create_lead_email)
|
||||
self._post_answer_and_trigger_next_step(discuss_channel, 'test2@example.com')
|
||||
|
||||
self.assertEqual(mail_channel.chatbot_current_step_id, self.step_create_lead_phone)
|
||||
self._post_answer_and_trigger_next_step(mail_channel, '123456')
|
||||
self.assertEqual(discuss_channel.chatbot_current_step_id, self.step_create_lead_phone)
|
||||
self._post_answer_and_trigger_next_step(discuss_channel, '123456')
|
||||
|
||||
self.assertEqual(mail_channel.chatbot_current_step_id, self.step_create_lead)
|
||||
self.assertEqual(discuss_channel.chatbot_current_step_id, self.step_create_lead)
|
||||
|
||||
@@ -31,7 +31,7 @@ class TestLivechatLead(TestCrmCommon):
|
||||
def test_crm_lead_creation_guest(self):
|
||||
""" Test customer set on lead: not if public, guest if not public """
|
||||
# public: should not be set as customer
|
||||
channel = self.env['mail.channel'].create({
|
||||
channel = self.env['discuss.channel'].create({
|
||||
'name': 'Chat with Visitor',
|
||||
'channel_partner_ids': [(4, self.user_anonymous.partner_id.id)]
|
||||
})
|
||||
@@ -48,7 +48,7 @@ class TestLivechatLead(TestCrmCommon):
|
||||
# 'base.public_user' is archived by default
|
||||
self.assertFalse(self.env.ref('base.public_user').active)
|
||||
|
||||
channel = self.env['mail.channel'].create({
|
||||
channel = self.env['discuss.channel'].create({
|
||||
'name': 'Chat with Visitor',
|
||||
'channel_partner_ids': [(4, self.env.ref('base.public_partner').id)]
|
||||
})
|
||||
@@ -69,7 +69,7 @@ class TestLivechatLead(TestCrmCommon):
|
||||
self.assertEqual(lead.partner_id, self.env['res.partner'])
|
||||
|
||||
# portal: should be set as customer
|
||||
channel = self.env['mail.channel'].create({
|
||||
channel = self.env['discuss.channel'].create({
|
||||
'name': 'Chat with Visitor',
|
||||
'channel_partner_ids': [(4, self.user_portal.partner_id.id)]
|
||||
})
|
||||
|
||||
@@ -128,7 +128,7 @@ class Challenge(models.Model):
|
||||
('yearly', "Yearly")
|
||||
], default='never',
|
||||
string="Report Frequency", required=True)
|
||||
report_message_group_id = fields.Many2one('mail.channel', string="Send a copy to", help="Group that will receive a copy of the report in addition to the user")
|
||||
report_message_group_id = fields.Many2one('discuss.channel', string="Send a copy to", help="Group that will receive a copy of the report in addition to the user")
|
||||
report_template_id = fields.Many2one('mail.template', default=lambda self: self._get_report_template(), string="Report Template", required=True)
|
||||
remind_update_delay = fields.Integer("Non-updated manual goals will be reminded after", help="Never reminded if no value or zero is specified.")
|
||||
last_report_date = fields.Date("Last Report Date", default=fields.Date.today)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
'views/hr_work_location_views.xml',
|
||||
'views/hr_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/mail_channel_views.xml',
|
||||
'views/discuss_channel_views.xml',
|
||||
'views/res_users.xml',
|
||||
'views/res_partner_views.xml',
|
||||
'views/hr_templates.xml',
|
||||
|
||||
@@ -14,7 +14,7 @@ from . import hr_plan_activity_type
|
||||
from . import hr_plan_employee_activity
|
||||
from . import hr_work_location
|
||||
from . import mail_alias
|
||||
from . import mail_channel
|
||||
from . import discuss_channel
|
||||
from . import models
|
||||
from . import res_config_settings
|
||||
from . import res_partner
|
||||
|
||||
@@ -6,7 +6,7 @@ from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class Channel(models.Model):
|
||||
_inherit = 'mail.channel'
|
||||
_inherit = 'discuss.channel'
|
||||
|
||||
subscription_department_ids = fields.Many2many(
|
||||
'hr.department', string='HR Departments',
|
||||
@@ -354,7 +354,7 @@ class HrEmployeePrivate(models.Model):
|
||||
return employees
|
||||
employee_departments = employees.department_id
|
||||
if employee_departments:
|
||||
self.env['mail.channel'].sudo().search([
|
||||
self.env['discuss.channel'].sudo().search([
|
||||
('subscription_department_ids', 'in', employee_departments.ids)
|
||||
])._subscribe_users_automatically()
|
||||
onboarding_notes_bodies = {}
|
||||
@@ -392,7 +392,7 @@ class HrEmployeePrivate(models.Model):
|
||||
if vals.get('department_id') or vals.get('user_id'):
|
||||
department_id = vals['department_id'] if vals.get('department_id') else self[:1].department_id.id
|
||||
# When added to a department or changing user, subscribe to the channels auto-subscribed by department
|
||||
self.env['mail.channel'].sudo().search([
|
||||
self.env['discuss.channel'].sudo().search([
|
||||
('subscription_department_ids', 'in', department_id)
|
||||
])._subscribe_users_automatically()
|
||||
return res
|
||||
|
||||
@@ -10,7 +10,7 @@ class TestChannel(TestHrCommon):
|
||||
def setUpClass(cls):
|
||||
super(TestChannel, cls).setUpClass()
|
||||
|
||||
cls.channel = cls.env['mail.channel'].create({'name': 'Test'})
|
||||
cls.channel = cls.env['discuss.channel'].create({'name': 'Test'})
|
||||
|
||||
emp0 = cls.env['hr.employee'].create({
|
||||
'user_id': cls.res_users_hr_officer.id,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" ?>
|
||||
<odoo><data>
|
||||
<record id="mail_channel_view_form_" model="ir.ui.view">
|
||||
<field name="name">mail.channel.view.form.inherit.hr</field>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="inherit_id" ref="mail.mail_channel_view_form"/>
|
||||
<record id="discuss_channel_view_form" model="ir.ui.view">
|
||||
<field name="name">discuss.channel.view.form.inherit.hr</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="inherit_id" ref="mail.discuss_channel_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='group_ids']" position="after">
|
||||
<field name="subscription_department_ids" widget="many2many_tags"
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.Thread" t-inherit-mode="extension">
|
||||
<xpath expr="//*[hasclass('o-mail-Thread')]" position="before">
|
||||
<div t-if="props.thread.model === 'mail.channel' and props.thread.correspondent and personaService.outOfOfficeText(props.thread.correspondent)" class="alert alert-primary" t-esc="personaService.outOfOfficeText(props.thread.correspondent)" role="alert"/>
|
||||
<div t-if="props.thread.model === 'discuss.channel' and props.thread.correspondent and personaService.outOfOfficeText(props.thread.correspondent)" class="alert alert-primary" t-esc="personaService.outOfOfficeText(props.thread.correspondent)" role="alert"/>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -9,11 +9,11 @@ QUnit.module("im_status");
|
||||
QUnit.test("on leave & online", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "leave_online" });
|
||||
const channelId = pyEnv["mail.channel"].create({ name: "General" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({
|
||||
author_id: partnerId,
|
||||
body: "not empty",
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
@@ -27,11 +27,11 @@ QUnit.test("on leave & online", async (assert) => {
|
||||
QUnit.test("on leave & away", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "leave_away" });
|
||||
const channelId = pyEnv["mail.channel"].create({ name: "General" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({
|
||||
author_id: partnerId,
|
||||
body: "not empty",
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
@@ -45,11 +45,11 @@ QUnit.test("on leave & away", async (assert) => {
|
||||
QUnit.test("on leave & offline", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo", im_status: "leave_offline" });
|
||||
const channelId = pyEnv["mail.channel"].create({ name: "General" });
|
||||
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
|
||||
pyEnv["mail.message"].create({
|
||||
author_id: partnerId,
|
||||
body: "not empty",
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
|
||||
@@ -10,7 +10,7 @@ QUnit.test("thread icon of a chat when correspondent is on leave & online", asyn
|
||||
im_status: "leave_online",
|
||||
name: "Demo",
|
||||
});
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: partnerId }],
|
||||
@@ -31,7 +31,7 @@ QUnit.test("thread icon of a chat when correspondent is on leave & away", async
|
||||
im_status: "leave_away",
|
||||
name: "Demo",
|
||||
});
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: partnerId }],
|
||||
@@ -52,7 +52,7 @@ QUnit.test("thread icon of a chat when correspondent is on leave & offline", asy
|
||||
im_status: "leave_offline",
|
||||
name: "Demo",
|
||||
});
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: partnerId }],
|
||||
|
||||
@@ -11,7 +11,7 @@ QUnit.test("out of office message on direct chat with out of office partner", as
|
||||
im_status: "leave_online",
|
||||
out_of_office_date_end: "2023-01-01",
|
||||
});
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: partnerId }],
|
||||
|
||||
@@ -41,7 +41,7 @@ class TestOutOfOffice(TestHrHolidaysCommon):
|
||||
partner = self.employee_hruser.user_id.partner_id
|
||||
partner2 = self.user_employee.partner_id
|
||||
|
||||
channel = self.env['mail.channel'].with_user(self.user_employee).with_context({
|
||||
channel = self.env['discuss.channel'].with_user(self.user_employee).with_context({
|
||||
'mail_create_nolog': True,
|
||||
'mail_create_nosubscribe': True,
|
||||
}).create({
|
||||
|
||||
@@ -20,7 +20,7 @@ Help your customers with this chat, and analyse their feedback.
|
||||
'data': [
|
||||
"security/im_livechat_channel_security.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"data/mail_shortcode_data.xml",
|
||||
"data/discuss_shortcode_data.xml",
|
||||
"data/mail_templates.xml",
|
||||
"data/im_livechat_channel_data.xml",
|
||||
"data/im_livechat_chatbot_data.xml",
|
||||
@@ -29,7 +29,7 @@ Help your customers with this chat, and analyse their feedback.
|
||||
'views/chatbot_script_step_views.xml',
|
||||
'views/chatbot_script_views.xml',
|
||||
"views/rating_rating_views.xml",
|
||||
"views/mail_channel_views.xml",
|
||||
"views/discuss_channel_views.xml",
|
||||
"views/im_livechat_channel_views.xml",
|
||||
"views/im_livechat_channel_templates.xml",
|
||||
"views/im_livechat_chatbot_templates.xml",
|
||||
@@ -40,7 +40,7 @@ Help your customers with this chat, and analyse their feedback.
|
||||
],
|
||||
'demo': [
|
||||
"data/im_livechat_channel_demo.xml",
|
||||
'data/mail_shortcode_demo.xml',
|
||||
'data/discuss_shortcode_demo.xml',
|
||||
],
|
||||
'depends': ["mail", "rating", "digest", "utm"],
|
||||
'installable': True,
|
||||
|
||||
@@ -10,32 +10,32 @@ class LivechatChatbotScriptController(http.Controller):
|
||||
@http.route('/chatbot/restart', type="json", auth="public", cors="*")
|
||||
def chatbot_restart(self, channel_uuid, chatbot_script_id):
|
||||
|
||||
mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
discuss_channel = request.env['discuss.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
chatbot = request.env['chatbot.script'].browse(chatbot_script_id)
|
||||
if not mail_channel or not chatbot.exists():
|
||||
if not discuss_channel or not chatbot.exists():
|
||||
return None
|
||||
|
||||
return mail_channel._chatbot_restart(chatbot).message_format()[0]
|
||||
return discuss_channel._chatbot_restart(chatbot).message_format()[0]
|
||||
|
||||
@http.route('/chatbot/post_welcome_steps', type="json", auth="public", cors="*")
|
||||
def chatbot_post_welcome_steps(self, channel_uuid, chatbot_script_id):
|
||||
mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
discuss_channel = request.env['discuss.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
chatbot = request.env['chatbot.script'].sudo().browse(chatbot_script_id)
|
||||
if not mail_channel or not chatbot.exists():
|
||||
if not discuss_channel or not chatbot.exists():
|
||||
return None
|
||||
|
||||
return chatbot._post_welcome_steps(mail_channel).message_format()
|
||||
return chatbot._post_welcome_steps(discuss_channel).message_format()
|
||||
|
||||
@http.route('/chatbot/answer/save', type="json", auth="public", cors="*")
|
||||
def chatbot_save_answer(self, channel_uuid, message_id, selected_answer_id):
|
||||
mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
discuss_channel = request.env['discuss.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
chatbot_message = request.env['chatbot.message'].sudo().search([
|
||||
('mail_message_id', '=', message_id),
|
||||
('mail_channel_id', '=', mail_channel.id),
|
||||
('discuss_channel_id', '=', discuss_channel.id),
|
||||
], limit=1)
|
||||
selected_answer = request.env['chatbot.script.answer'].sudo().browse(selected_answer_id)
|
||||
|
||||
if not mail_channel or not chatbot_message or not selected_answer.exists():
|
||||
if not discuss_channel or not chatbot_message or not selected_answer.exists():
|
||||
return
|
||||
|
||||
if selected_answer in chatbot_message.script_step_id.answer_ids:
|
||||
@@ -43,20 +43,20 @@ class LivechatChatbotScriptController(http.Controller):
|
||||
|
||||
@http.route('/chatbot/step/trigger', type="json", auth="public", cors="*")
|
||||
def chatbot_trigger_step(self, channel_uuid, chatbot_script_id=None):
|
||||
mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
if not mail_channel:
|
||||
discuss_channel = request.env['discuss.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
if not discuss_channel:
|
||||
return None
|
||||
|
||||
next_step = False
|
||||
if mail_channel.chatbot_current_step_id:
|
||||
chatbot = mail_channel.chatbot_current_step_id.chatbot_script_id
|
||||
user_messages = mail_channel.message_ids.filtered(
|
||||
if discuss_channel.chatbot_current_step_id:
|
||||
chatbot = discuss_channel.chatbot_current_step_id.chatbot_script_id
|
||||
user_messages = discuss_channel.message_ids.filtered(
|
||||
lambda message: message.author_id != chatbot.operator_partner_id
|
||||
)
|
||||
user_answer = request.env['mail.message'].sudo()
|
||||
if user_messages:
|
||||
user_answer = user_messages.sorted(lambda message: message.id)[-1]
|
||||
next_step = mail_channel.chatbot_current_step_id._process_answer(mail_channel, user_answer.body)
|
||||
next_step = discuss_channel.chatbot_current_step_id._process_answer(discuss_channel, user_answer.body)
|
||||
elif chatbot_script_id: # when restarting, we don't have a "current step" -> set "next" as first step of the script
|
||||
chatbot = request.env['chatbot.script'].sudo().browse(chatbot_script_id)
|
||||
if chatbot.exists():
|
||||
@@ -65,19 +65,19 @@ class LivechatChatbotScriptController(http.Controller):
|
||||
if not next_step:
|
||||
return None
|
||||
|
||||
posted_message = next_step._process_step(mail_channel)
|
||||
posted_message = next_step._process_step(discuss_channel)
|
||||
return {
|
||||
'chatbot_posted_message': posted_message.message_format()[0] if posted_message else None,
|
||||
'chatbot_step': {
|
||||
'chatbot_operator_found': next_step.step_type == 'forward_operator' and len(
|
||||
mail_channel.channel_member_ids) > 2,
|
||||
discuss_channel.channel_member_ids) > 2,
|
||||
'chatbot_script_step_id': next_step.id,
|
||||
'chatbot_step_answers': [{
|
||||
'id': answer.id,
|
||||
'label': answer.name,
|
||||
'redirect_link': answer.redirect_link,
|
||||
} for answer in next_step.answer_ids],
|
||||
'chatbot_step_is_last': next_step._is_last_step(mail_channel),
|
||||
'chatbot_step_is_last': next_step._is_last_step(discuss_channel),
|
||||
'chatbot_step_message': plaintext2html(next_step.message) if not is_html_empty(next_step.message) else False,
|
||||
'chatbot_step_type': next_step.step_type,
|
||||
}
|
||||
@@ -85,18 +85,18 @@ class LivechatChatbotScriptController(http.Controller):
|
||||
|
||||
@http.route('/chatbot/step/validate_email', type="json", auth="public", cors="*")
|
||||
def chatbot_validate_email(self, channel_uuid):
|
||||
mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
if not mail_channel or not mail_channel.chatbot_current_step_id:
|
||||
discuss_channel = request.env['discuss.channel'].sudo().search([('uuid', '=', channel_uuid)], limit=1)
|
||||
if not discuss_channel or not discuss_channel.chatbot_current_step_id:
|
||||
return None
|
||||
|
||||
chatbot = mail_channel.chatbot_current_step_id.chatbot_script_id
|
||||
user_messages = mail_channel.message_ids.filtered(
|
||||
chatbot = discuss_channel.chatbot_current_step_id.chatbot_script_id
|
||||
user_messages = discuss_channel.message_ids.filtered(
|
||||
lambda message: message.author_id != chatbot.operator_partner_id
|
||||
)
|
||||
|
||||
if user_messages:
|
||||
user_answer = user_messages.sorted(lambda message: message.id)[-1]
|
||||
result = chatbot._validate_email(user_answer.body, mail_channel)
|
||||
result = chatbot._validate_email(user_answer.body, discuss_channel)
|
||||
|
||||
if result['posted_message']:
|
||||
result['posted_message'] = result['posted_message'].message_format()[0]
|
||||
|
||||
@@ -134,7 +134,7 @@ class LivechatController(http.Controller):
|
||||
if chatbot_script_id:
|
||||
chatbot_script = request.env['chatbot.script'].sudo().browse(chatbot_script_id)
|
||||
|
||||
return request.env["im_livechat.channel"].with_context(lang=False).sudo().browse(channel_id)._open_livechat_mail_channel(
|
||||
return request.env["im_livechat.channel"].with_context(lang=False).sudo().browse(channel_id)._open_livechat_discuss_channel(
|
||||
anonymous_name,
|
||||
previous_operator_id=previous_operator_id,
|
||||
chatbot_script=chatbot_script,
|
||||
@@ -145,7 +145,7 @@ class LivechatController(http.Controller):
|
||||
|
||||
@http.route('/im_livechat/feedback', type='json', auth='public', cors="*")
|
||||
def feedback(self, uuid, rate, reason=None, **kwargs):
|
||||
channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)], limit=1)
|
||||
channel = request.env['discuss.channel'].sudo().search([('uuid', '=', uuid)], limit=1)
|
||||
if channel:
|
||||
# limit the creation : only ONE rating per session
|
||||
values = {
|
||||
@@ -157,7 +157,7 @@ class LivechatController(http.Controller):
|
||||
if not channel.rating_ids:
|
||||
values.update({
|
||||
'res_id': channel.id,
|
||||
'res_model_id': request.env['ir.model']._get_id('mail.channel'),
|
||||
'res_model_id': request.env['ir.model']._get_id('discuss.channel'),
|
||||
})
|
||||
# find the partner (operator)
|
||||
if channel.channel_partner_ids:
|
||||
@@ -175,7 +175,7 @@ class LivechatController(http.Controller):
|
||||
@http.route('/im_livechat/history', type="json", auth="public", cors="*")
|
||||
def history_pages(self, pid, channel_uuid, page_history=None):
|
||||
partner_ids = (pid, request.env.user.partner_id.id)
|
||||
channel = request.env['mail.channel'].sudo().search([('uuid', '=', channel_uuid), ('channel_partner_ids', 'in', partner_ids)])
|
||||
channel = request.env['discuss.channel'].sudo().search([('uuid', '=', channel_uuid), ('channel_partner_ids', 'in', partner_ids)])
|
||||
if channel:
|
||||
channel._send_history_message(pid, page_history)
|
||||
return True
|
||||
@@ -186,17 +186,17 @@ class LivechatController(http.Controller):
|
||||
:param uuid: (string) the UUID of the livechat channel
|
||||
:param is_typing: (boolean) tells whether the website user is typing or not.
|
||||
"""
|
||||
channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)])
|
||||
channel = request.env['discuss.channel'].sudo().search([('uuid', '=', uuid)])
|
||||
if not channel:
|
||||
raise NotFound()
|
||||
channel_member = channel.env['mail.channel.member'].search([('channel_id', '=', channel.id), ('partner_id', '=', request.env.user.partner_id.id)])
|
||||
channel_member = channel.env['discuss.channel.member'].search([('channel_id', '=', channel.id), ('partner_id', '=', request.env.user.partner_id.id)])
|
||||
if not channel_member:
|
||||
raise NotFound()
|
||||
channel_member._notify_typing(is_typing=is_typing)
|
||||
|
||||
@http.route('/im_livechat/email_livechat_transcript', type='json', auth='public', cors="*")
|
||||
def email_livechat_transcript(self, uuid, email):
|
||||
channel = request.env['mail.channel'].sudo().search([
|
||||
channel = request.env['discuss.channel'].sudo().search([
|
||||
('channel_type', '=', 'livechat'),
|
||||
('uuid', '=', uuid)], limit=1)
|
||||
if channel:
|
||||
@@ -208,6 +208,6 @@ class LivechatController(http.Controller):
|
||||
This will clean the chat request and warn the operator that the conversation is over.
|
||||
This allows also to re-send a new chat request to the visitor, as while the visitor is
|
||||
in conversation with an operator, it's not possible to send the visitor a chat request."""
|
||||
mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)])
|
||||
if mail_channel:
|
||||
mail_channel._close_livechat_session()
|
||||
discuss_channel = request.env['discuss.channel'].sudo().search([('uuid', '=', uuid)])
|
||||
if discuss_channel:
|
||||
discuss_channel._close_livechat_session()
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<field eval="[(4, ref('base.user_demo'))]" name="user_ids"/>
|
||||
</record>
|
||||
<!-- Session 0 -->
|
||||
<record id="im_livechat_mail_channel_data_0" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_0" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_admin"/>
|
||||
@@ -26,56 +26,56 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_1" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_1</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_0"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_0"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_admin"/>
|
||||
<field eval="False" name="partner_id"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_0')], 5, 'LIVECHAT_1', None, 'Good Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_0')], 5, 'LIVECHAT_1', None, 'Good Job')"/>
|
||||
<record id="im_livechat_mail_message_5_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_0"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_0"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">You're welcome, have a nice day!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-0, minutes=5)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_4_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_0"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_0"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Great! Thanks for the info</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-0, minutes=4)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_3_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_0"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_0"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Yes, you can use our Timesheets application to record your time efficiently!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-0, minutes=3)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_2_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_0"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_0"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">I'm looking for an application to record my timesheet, any tips?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-0, minutes=2)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_1_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_0"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_0"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-0, minutes=1)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 1 -->
|
||||
<record id="im_livechat_mail_channel_data_1" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_1" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_demo"/>
|
||||
@@ -84,56 +84,56 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_2" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_2</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_1"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_1"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_demo"/>
|
||||
<field eval="False" name="partner_id"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_1')], 5, 'LIVECHAT_2', None, 'Super Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_1')], 5, 'LIVECHAT_2', None, 'Super Job')"/>
|
||||
<record id="im_livechat_mail_message_10_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_1"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="body">You're welcome, enjoy Odoo!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-1, minutes=10)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_9_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_1"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Awesome, thanks!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-1, minutes=9)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_8_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_1"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="body">Yes, we just released a new application called Social Marketing that should fit your needs! Check it out :)</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-1, minutes=8)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_7_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_1"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">I was wondering if Odoo has an application to easily manage social media for my business..</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-1, minutes=7)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_6_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_1"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-1, minutes=6)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 2 -->
|
||||
<record id="im_livechat_mail_channel_data_2" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_2" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_admin"/>
|
||||
@@ -142,49 +142,49 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_3" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_3</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_2"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_2"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_admin"/>
|
||||
<field name="partner_id" ref="base.partner_demo_portal"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_2')], 5, 'LIVECHAT_3', None, 'Mega Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_2')], 5, 'LIVECHAT_3', None, 'Mega Job')"/>
|
||||
|
||||
<record id="im_livechat_mail_message_14_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_2"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_2"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo_portal"/>
|
||||
<field name="body">Oh :(</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-2, minutes=14)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_13_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_2"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_2"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Nope, sorry to disappoint :(</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-2, minutes=13)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_12_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_2"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_2"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo_portal"/>
|
||||
<field name="body">Hello, are you single?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-2, minutes=12)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_11_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_2"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_2"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-1, days=-2, minutes=11)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 3 -->
|
||||
<record id="im_livechat_mail_channel_data_3" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_3" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_demo"/>
|
||||
@@ -193,41 +193,41 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_4" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_4</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_3"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_3"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_demo"/>
|
||||
<field name="partner_id" ref="base.partner_demo_portal"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_3')], 5, 'LIVECHAT_4', None, 'Good Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_3')], 5, 'LIVECHAT_4', None, 'Good Job')"/>
|
||||
|
||||
<record id="im_livechat_mail_message_17_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_3"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_3"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo_portal"/>
|
||||
<field name="body">Thanks for the info, I'll look into it!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-3, minutes=17)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_16_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_3"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_3"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="body">Hello Joel Willis, you're at the right place! You can customize Odoo using our Studio application in just a few clicks.</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-3, minutes=16)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_15_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_3"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_3"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo_portal"/>
|
||||
<field name="body">Hello, I'm looking for a software that can be easily updated with my needs.</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-3, minutes=15)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 4 -->
|
||||
<record id="im_livechat_mail_channel_data_4" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_4" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_admin"/>
|
||||
@@ -236,48 +236,48 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_5" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_5</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_4"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_4"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_admin"/>
|
||||
<field eval="False" name="partner_id"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_4')], 5, 'LIVECHAT_5', None, 'Super Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_4')], 5, 'LIVECHAT_5', None, 'Super Job')"/>
|
||||
<record id="im_livechat_mail_message_21_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_4"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_4"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Ok.. Will do, thanks</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-4, minutes=21)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_20_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_4"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_4"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Hi, if you need help with your database, feel free to contact our support via http://www.odoo.com/help</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-4, minutes=20)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_19_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_4"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_4"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Hello, it seems that I can't log in to my database. Can you help?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-4, minutes=19)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_18_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_4"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_4"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-2, days=-4, minutes=18)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 5 -->
|
||||
<record id="im_livechat_mail_channel_data_5" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_5" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_admin"/>
|
||||
@@ -286,48 +286,48 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_6" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_6</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_5"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_5"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_admin"/>
|
||||
<field eval="False" name="partner_id"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_5')], 5, 'LIVECHAT_6', None, 'Good Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_5')], 5, 'LIVECHAT_6', None, 'Good Job')"/>
|
||||
<record id="im_livechat_mail_message_25_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_5"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_5"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Thanks!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-5, minutes=25)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_24_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_5"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_5"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Yes, of course, you can find it here: https://www.odoo.com/documentation/master/</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-5, minutes=24)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_23_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_5"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_5"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Hello, I'm a bit lost in the Invetory module, is there some documentation I could find?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-5, minutes=23)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_22_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_5"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_5"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-5, minutes=22)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 6 -->
|
||||
<record id="im_livechat_mail_channel_data_6" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_6" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_admin"/>
|
||||
@@ -336,48 +336,48 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_7" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_7</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_6"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_6"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_admin"/>
|
||||
<field name="partner_id" ref="base.partner_demo_portal"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_6')], 5, 'LIVECHAT_7', None, 'Super Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_6')], 5, 'LIVECHAT_7', None, 'Super Job')"/>
|
||||
<record id="im_livechat_mail_message_29_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_6"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_6"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo_portal"/>
|
||||
<field name="body">Good to hear, thanks!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-6, minutes=29)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_28_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_6"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_6"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Joel Willis, you'll need our Inventory and Sales application to do so. You can try them for 15 days, FOR FREE :)</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-6, minutes=28)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_27_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_6"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_6"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo_portal"/>
|
||||
<field name="body">Hi, I need a software to easily manage my stock, and generate sales orders.</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-6, minutes=27)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_26_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_6"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_6"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-6, minutes=26)" name="date"/>
|
||||
</record>
|
||||
<!-- Session 7 -->
|
||||
<record id="im_livechat_mail_channel_data_7" model="mail.channel">
|
||||
<record id="im_livechat_discuss_channel_data_7" model="discuss.channel">
|
||||
<field name="channel_type">livechat</field>
|
||||
<field name="livechat_channel_id" ref="im_livechat_channel_data"/>
|
||||
<field name="livechat_operator_id" ref="base.partner_demo"/>
|
||||
@@ -386,48 +386,48 @@
|
||||
</record>
|
||||
<record id="im_livechat_rating_8" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_8</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_7"/>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_7"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_demo"/>
|
||||
<field eval="False" name="partner_id"/>
|
||||
<field eval="True" name="consumed"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_mail_channel_data_7')], 5, 'LIVECHAT_8', None, 'Super Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.im_livechat_discuss_channel_data_7')], 5, 'LIVECHAT_8', None, 'Super Job')"/>
|
||||
<record id="im_livechat_mail_message_33_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_7"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_7"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">I'm great, thanks for asking!</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-7, minutes=33)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_32_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_7"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_7"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="body">I'm fine, and you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-7, minutes=32)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_31_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_7"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_7"/>
|
||||
<field name="message_type">email</field>
|
||||
<field eval="False" name="author_id"/>
|
||||
<field name="body">Heeeey Marc, how are you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-7, minutes=31)" name="date"/>
|
||||
</record>
|
||||
<record id="im_livechat_mail_message_30_data" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_mail_channel_data_7"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="im_livechat.im_livechat_discuss_channel_data_7"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field eval="DateTime.today() + relativedelta(months=-3, days=-7, minutes=30)" name="date"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_channel_livechat_1" model="mail.channel">
|
||||
<record id="discuss_channel_livechat_1" model="discuss.channel">
|
||||
<field name="name">Visitor, Mitchell Admin</field>
|
||||
<field name="livechat_operator_id" ref="base.partner_admin"/>
|
||||
<field name="livechat_channel_id" ref="im_livechat.im_livechat_channel_data"/>
|
||||
@@ -441,16 +441,16 @@
|
||||
<field name="date" eval="datetime.now() - timedelta(days=1)"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1)"/>
|
||||
<field name="body">Hi</field>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
</record>
|
||||
<record id="mail_message_livechat_2" model="mail.message">
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="date" eval="datetime.now() - timedelta(days=1, seconds=-15)"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1, seconds=-15)"/>
|
||||
<field name="body">Hello, how may I help you?</field>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
</record>
|
||||
<record id="mail_message_livechat_3" model="mail.message">
|
||||
<field name="author_id" eval="False"/>
|
||||
@@ -458,16 +458,16 @@
|
||||
<field name="date" eval="datetime.now() - timedelta(days=1, seconds=-25)"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1, seconds=-25)"/>
|
||||
<field name="body">I would like to know more about the CRM application</field>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
</record>
|
||||
<record id="mail_message_livechat_4" model="mail.message">
|
||||
<field name="author_id" ref="base.partner_admin"/>
|
||||
<field name="date" eval="datetime.now() - timedelta(days=1, seconds=-33)"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1, seconds=-33)"/>
|
||||
<field name="body">The CRM application helps you to track leads, close opportunities and get accurate forecasts. You can test it for free on our website.</field>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
</record>
|
||||
<record id="mail_message_livechat_5" model="mail.message">
|
||||
<field name="author_id" eval="False"/>
|
||||
@@ -475,8 +475,8 @@
|
||||
<field name="date" eval="datetime.now() - timedelta(days=1, seconds=-42)"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1, seconds=-42)"/>
|
||||
<field name="body">Great, thanks!</field>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
</record>
|
||||
<record id="mail_message_livechat_6" model="mail.message">
|
||||
<field name="author_id" eval="False"/>
|
||||
@@ -484,19 +484,19 @@
|
||||
<field name="date" eval="datetime.now() - timedelta(days=1, seconds=-53)"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1, seconds=-53)"/>
|
||||
<field name="body">Rating: :-)</field>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
<field name="model">discuss.channel</field>
|
||||
</record>
|
||||
<record id="rating_rating_livechat_1" model="rating.rating">
|
||||
<field name="access_token">LIVECHAT_9</field>
|
||||
<field name="res_model_id" ref="mail.model_mail_channel"/>
|
||||
<field name="res_model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="rated_partner_id" ref="base.partner_admin"/>
|
||||
<field name="partner_id" ref="base.partner_admin"/>
|
||||
<field name="create_date" eval="datetime.now() - timedelta(days=1, seconds=-53)"/>
|
||||
<field name="res_id" ref="im_livechat.mail_channel_livechat_1"/>
|
||||
<field name="res_id" ref="im_livechat.discuss_channel_livechat_1"/>
|
||||
</record>
|
||||
<function model="mail.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.mail_channel_livechat_1')], 5, 'LIVECHAT_9', None, 'Super Job')"/>
|
||||
<function model="discuss.channel" name="rating_apply"
|
||||
eval="([ref('im_livechat.discuss_channel_livechat_1')], 5, 'LIVECHAT_9', None, 'Super Job')"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -7,8 +7,8 @@ from . import chatbot_script_step
|
||||
from . import res_users
|
||||
from . import res_partner
|
||||
from . import im_livechat_channel
|
||||
from . import mail_channel
|
||||
from . import mail_channel_member
|
||||
from . import discuss_channel
|
||||
from . import discuss_channel_member
|
||||
from . import mail_message
|
||||
from . import res_users_settings
|
||||
from . import rating_rating
|
||||
|
||||
@@ -13,10 +13,10 @@ class ChatbotMailMessage(models.Model):
|
||||
_name = 'chatbot.message'
|
||||
_description = 'Chatbot Message'
|
||||
_order = 'create_date desc, id desc'
|
||||
_rec_name = 'mail_channel_id'
|
||||
_rec_name = 'discuss_channel_id'
|
||||
|
||||
mail_message_id = fields.Many2one('mail.message', string='Related Mail Message', required=True, ondelete="cascade")
|
||||
mail_channel_id = fields.Many2one('mail.channel', string='Discussion Channel', required=True, ondelete="cascade")
|
||||
discuss_channel_id = fields.Many2one('discuss.channel', string='Discussion Channel', required=True, ondelete="cascade")
|
||||
script_step_id = fields.Many2one(
|
||||
'chatbot.script.step', string='Chatbot Step', required=True, ondelete='cascade')
|
||||
user_script_answer_id = fields.Many2one('chatbot.script.answer', string="User's answer", ondelete="set null")
|
||||
|
||||
@@ -135,7 +135,7 @@ class ChatbotScript(models.Model):
|
||||
end user.
|
||||
|
||||
This is important because we need to display those welcoming steps in a special fashion on
|
||||
the frontend, since those are not inserted into the mail.channel as actual mail.messages,
|
||||
the frontend, since those are not inserted into the discuss.channel as actual mail.messages,
|
||||
to avoid bloating the channels with bot messages if the end-user never interacts with it. """
|
||||
self.ensure_one()
|
||||
|
||||
@@ -147,21 +147,21 @@ class ChatbotScript(models.Model):
|
||||
|
||||
return welcome_steps
|
||||
|
||||
def _post_welcome_steps(self, mail_channel):
|
||||
def _post_welcome_steps(self, discuss_channel):
|
||||
""" Welcome messages are only posted after the visitor's first interaction with the chatbot.
|
||||
See 'chatbot.script#_get_welcome_steps()' for more details.
|
||||
|
||||
Side note: it is important to set the 'chatbot_current_step_id' on each iteration so that
|
||||
it's correctly set when going into 'mail_channel#_message_post_after_hook()'. """
|
||||
it's correctly set when going into 'discuss_channel#_message_post_after_hook()'. """
|
||||
|
||||
self.ensure_one()
|
||||
posted_messages = self.env['mail.message']
|
||||
|
||||
for welcome_step in self._get_welcome_steps():
|
||||
mail_channel.chatbot_current_step_id = welcome_step.id
|
||||
discuss_channel.chatbot_current_step_id = welcome_step.id
|
||||
|
||||
if not is_html_empty(welcome_step.message):
|
||||
posted_messages += mail_channel.with_context(mail_create_nosubscribe=True).message_post(
|
||||
posted_messages += discuss_channel.with_context(mail_create_nosubscribe=True).message_post(
|
||||
author_id=self.operator_partner_id.id,
|
||||
body=plaintext2html(welcome_step.message),
|
||||
message_type='comment',
|
||||
@@ -194,7 +194,7 @@ class ChatbotScript(models.Model):
|
||||
]
|
||||
}
|
||||
|
||||
def _validate_email(self, email_address, mail_channel):
|
||||
def _validate_email(self, email_address, discuss_channel):
|
||||
email_address = html2plaintext(email_address)
|
||||
email_normalized = email_normalize(email_address)
|
||||
|
||||
@@ -205,7 +205,7 @@ class ChatbotScript(models.Model):
|
||||
"'%(input_email)s' does not look like a valid email. Can you please try again?",
|
||||
input_email=email_address
|
||||
)
|
||||
posted_message = mail_channel._chatbot_post_message(self, plaintext2html(error_message))
|
||||
posted_message = discuss_channel._chatbot_post_message(self, plaintext2html(error_message))
|
||||
|
||||
return {
|
||||
'success': bool(email_normalized),
|
||||
|
||||
@@ -120,24 +120,24 @@ class ChatbotScriptStep(models.Model):
|
||||
# Business Methods
|
||||
# --------------------------
|
||||
|
||||
def _chatbot_prepare_customer_values(self, mail_channel, create_partner=True, update_partner=True):
|
||||
""" Common method that allows retreiving default customer values from the mail.channel
|
||||
def _chatbot_prepare_customer_values(self, discuss_channel, create_partner=True, update_partner=True):
|
||||
""" Common method that allows retreiving default customer values from the discuss.channel
|
||||
following a chatbot.script.
|
||||
|
||||
This method will return a dict containing the 'customer' values such as:
|
||||
{
|
||||
'partner': The created partner (see 'create_partner') or the partner from the
|
||||
environment if not public
|
||||
'email': The email extracted from the mail.channel messages
|
||||
'email': The email extracted from the discuss.channel messages
|
||||
(see step_type 'question_email')
|
||||
'phone': The phone extracted from the mail.channel messages
|
||||
'phone': The phone extracted from the discuss.channel messages
|
||||
(see step_type 'question_phone')
|
||||
'description': A default description containing the "Please contact me on" and "Please
|
||||
call me on" with the related email and phone numbers.
|
||||
Can be used as a default description to create leads or tickets for example.
|
||||
}
|
||||
|
||||
:param record mail_channel: the mail.channel holding the visitor's conversation with the bot.
|
||||
:param record discuss_channel: the discuss.channel holding the visitor's conversation with the bot.
|
||||
:param bool create_partner: whether or not to create a res.partner is the current user is public.
|
||||
Defaults to True.
|
||||
:param bool update_partner: whether or not to set update the email and phone on the res.partner
|
||||
@@ -146,7 +146,7 @@ class ChatbotScriptStep(models.Model):
|
||||
:return dict: a dict containing the customer values."""
|
||||
|
||||
partner = False
|
||||
user_inputs = mail_channel._chatbot_find_customer_values_in_messages({
|
||||
user_inputs = discuss_channel._chatbot_find_customer_values_in_messages({
|
||||
'question_email': 'email',
|
||||
'question_phone': 'phone',
|
||||
})
|
||||
@@ -254,18 +254,18 @@ class ChatbotScriptStep(models.Model):
|
||||
return step
|
||||
return self.env['chatbot.script.step']
|
||||
|
||||
def _is_last_step(self, mail_channel=False):
|
||||
def _is_last_step(self, discuss_channel=False):
|
||||
self.ensure_one()
|
||||
mail_channel = mail_channel or self.env['mail.channel']
|
||||
discuss_channel = discuss_channel or self.env['discuss.channel']
|
||||
|
||||
# if it's not a question and if there is no next step, then we end the script
|
||||
if self.step_type != 'question_selection' and not self._fetch_next_step(
|
||||
mail_channel.chatbot_message_ids.user_script_answer_id):
|
||||
discuss_channel.chatbot_message_ids.user_script_answer_id):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _process_answer(self, mail_channel, message_body):
|
||||
def _process_answer(self, discuss_channel, message_body):
|
||||
""" Method called when the user reacts to the current chatbot.script step.
|
||||
For most chatbot.script.step#step_types it simply returns the next chatbot.script.step of
|
||||
the script (see '_fetch_next_step').
|
||||
@@ -274,7 +274,7 @@ class ChatbotScriptStep(models.Model):
|
||||
we store the user raw answer (the mail message HTML body) into the chatbot.message in order
|
||||
to be able to recover it later (see '_chatbot_prepare_customer_values').
|
||||
|
||||
:param mail_channel:
|
||||
:param discuss_channel:
|
||||
:param message_body:
|
||||
:return: script step to display next
|
||||
:rtype: 'chatbot.script.step' """
|
||||
@@ -288,7 +288,7 @@ class ChatbotScriptStep(models.Model):
|
||||
|
||||
if self.step_type in ['question_email', 'question_phone']:
|
||||
chatbot_message = self.env['chatbot.message'].search([
|
||||
('mail_channel_id', '=', mail_channel.id),
|
||||
('discuss_channel_id', '=', discuss_channel.id),
|
||||
('script_step_id', '=', self.id),
|
||||
], limit=1)
|
||||
|
||||
@@ -296,9 +296,9 @@ class ChatbotScriptStep(models.Model):
|
||||
chatbot_message.write({'user_raw_answer': message_body})
|
||||
self.env.flush_all()
|
||||
|
||||
return self._fetch_next_step(mail_channel.chatbot_message_ids.user_script_answer_id)
|
||||
return self._fetch_next_step(discuss_channel.chatbot_message_ids.user_script_answer_id)
|
||||
|
||||
def _process_step(self, mail_channel):
|
||||
def _process_step(self, discuss_channel):
|
||||
""" When we reach a chatbot.step in the script we need to do some processing on behalf of
|
||||
the bot. Which is for most chatbot.script.step#step_types just posting the message field.
|
||||
|
||||
@@ -310,14 +310,14 @@ class ChatbotScriptStep(models.Model):
|
||||
|
||||
self.ensure_one()
|
||||
# We change the current step to the new step
|
||||
mail_channel.chatbot_current_step_id = self.id
|
||||
discuss_channel.chatbot_current_step_id = self.id
|
||||
|
||||
if self.step_type == 'forward_operator':
|
||||
return self._process_step_forward_operator(mail_channel)
|
||||
return self._process_step_forward_operator(discuss_channel)
|
||||
|
||||
return mail_channel._chatbot_post_message(self.chatbot_script_id, plaintext2html(self.message))
|
||||
return discuss_channel._chatbot_post_message(self.chatbot_script_id, plaintext2html(self.message))
|
||||
|
||||
def _process_step_forward_operator(self, mail_channel):
|
||||
def _process_step_forward_operator(self, discuss_channel):
|
||||
""" Special type of step that will add a human operator to the conversation when reached,
|
||||
which stops the script and allow the visitor to discuss with a real person.
|
||||
|
||||
@@ -328,28 +328,28 @@ class ChatbotScriptStep(models.Model):
|
||||
human_operator = False
|
||||
posted_message = False
|
||||
|
||||
if mail_channel.livechat_channel_id:
|
||||
human_operator = mail_channel.livechat_channel_id._get_random_operator()
|
||||
if discuss_channel.livechat_channel_id:
|
||||
human_operator = discuss_channel.livechat_channel_id._get_random_operator()
|
||||
|
||||
# handle edge case where we found yourself as available operator -> don't do anything
|
||||
# it will act as if no-one is available (which is fine)
|
||||
if human_operator and human_operator != self.env.user:
|
||||
mail_channel.sudo().add_members(
|
||||
discuss_channel.sudo().add_members(
|
||||
human_operator.partner_id.ids,
|
||||
open_chat_window=True,
|
||||
post_joined_message=False)
|
||||
|
||||
if self.message:
|
||||
# first post the message of the step (if we have one)
|
||||
posted_message = mail_channel._chatbot_post_message(self.chatbot_script_id, plaintext2html(self.message))
|
||||
posted_message = discuss_channel._chatbot_post_message(self.chatbot_script_id, plaintext2html(self.message))
|
||||
|
||||
# then post a small custom 'Operator has joined' notification
|
||||
mail_channel._chatbot_post_message(
|
||||
discuss_channel._chatbot_post_message(
|
||||
self.chatbot_script_id,
|
||||
Markup('<div class="o_mail_notification">%s</div>') % _('%s has joined', human_operator.partner_id.name))
|
||||
|
||||
mail_channel._broadcast(human_operator.partner_id.ids)
|
||||
mail_channel.channel_pin(pinned=True)
|
||||
discuss_channel._broadcast(human_operator.partner_id.ids)
|
||||
discuss_channel.channel_pin(pinned=True)
|
||||
|
||||
return posted_message
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class Digest(models.Model):
|
||||
kpi_livechat_response_value = fields.Float(digits=(16, 2), compute='_compute_kpi_livechat_response_value')
|
||||
|
||||
def _compute_kpi_livechat_rating_value(self):
|
||||
channels = self.env['mail.channel'].search([('channel_type', '=', 'livechat')])
|
||||
channels = self.env['discuss.channel'].search([('channel_type', '=', 'livechat')])
|
||||
start, end, __ = self._get_kpi_compute_parameters()
|
||||
domain = [
|
||||
('create_date', '>=', start),
|
||||
@@ -29,7 +29,7 @@ class Digest(models.Model):
|
||||
|
||||
def _compute_kpi_livechat_conversations_value(self):
|
||||
start, end, __ = self._get_kpi_compute_parameters()
|
||||
self.kpi_livechat_conversations_value = self.env['mail.channel'].search_count([
|
||||
self.kpi_livechat_conversations_value = self.env['discuss.channel'].search_count([
|
||||
('channel_type', '=', 'livechat'),
|
||||
('create_date', '>=', start), ('create_date', '<', end),
|
||||
])
|
||||
|
||||
+12
-12
@@ -7,14 +7,14 @@ from odoo.tools import email_normalize, html_escape, html2plaintext, plaintext2h
|
||||
from markupsafe import Markup
|
||||
|
||||
|
||||
class MailChannel(models.Model):
|
||||
class DiscussChannel(models.Model):
|
||||
""" Chat Session
|
||||
Reprensenting a conversation between users.
|
||||
It extends the base method for anonymous usage.
|
||||
"""
|
||||
|
||||
_name = 'mail.channel'
|
||||
_inherit = ['rating.mixin', 'mail.channel']
|
||||
_name = 'discuss.channel'
|
||||
_inherit = ['rating.mixin', 'discuss.channel']
|
||||
|
||||
anonymous_name = fields.Char('Anonymous Name')
|
||||
channel_type = fields.Selection(selection_add=[('livechat', 'Livechat Conversation')], ondelete={'livechat': 'cascade'})
|
||||
@@ -22,20 +22,20 @@ class MailChannel(models.Model):
|
||||
livechat_channel_id = fields.Many2one('im_livechat.channel', 'Channel')
|
||||
livechat_operator_id = fields.Many2one('res.partner', string='Operator')
|
||||
chatbot_current_step_id = fields.Many2one('chatbot.script.step', string='Chatbot Current Step')
|
||||
chatbot_message_ids = fields.One2many('chatbot.message', 'mail_channel_id', string='Chatbot Messages')
|
||||
chatbot_message_ids = fields.One2many('chatbot.message', 'discuss_channel_id', string='Chatbot Messages')
|
||||
country_id = fields.Many2one('res.country', string="Country", help="Country of the visitor of the channel")
|
||||
|
||||
_sql_constraints = [('livechat_operator_id', "CHECK((channel_type = 'livechat' and livechat_operator_id is not null) or (channel_type != 'livechat'))",
|
||||
'Livechat Operator ID is required for a channel of type livechat.')]
|
||||
|
||||
def _compute_is_chat(self):
|
||||
super(MailChannel, self)._compute_is_chat()
|
||||
super()._compute_is_chat()
|
||||
for record in self:
|
||||
if record.channel_type == 'livechat':
|
||||
record.is_chat = True
|
||||
|
||||
def _channel_message_notifications(self, message, message_format=False):
|
||||
""" When a anonymous user create a mail.channel, the operator is not notify (to avoid massive polling when
|
||||
""" When a anonymous user create a discuss.channel, the operator is not notify (to avoid massive polling when
|
||||
clicking on livechat button). So when the anonymous person is sending its FIRST message, the channel header
|
||||
should be added to the notification, since the user cannot be listining to the channel.
|
||||
"""
|
||||
@@ -43,7 +43,7 @@ class MailChannel(models.Model):
|
||||
for channel in self:
|
||||
# add uuid to allow anonymous to listen
|
||||
if channel.channel_type == 'livechat':
|
||||
notifications.append([channel.uuid, 'mail.channel/new_message', notifications[0][2]])
|
||||
notifications.append([channel.uuid, 'discuss.channel/new_message', notifications[0][2]])
|
||||
if not message.author_id:
|
||||
unpinned_members = self.channel_member_ids.filtered(lambda member: not member.is_pinned)
|
||||
if unpinned_members:
|
||||
@@ -74,11 +74,11 @@ class MailChannel(models.Model):
|
||||
hours = 1 # never remove empty session created within the last hour
|
||||
self.env.cr.execute("""
|
||||
SELECT id as id
|
||||
FROM mail_channel C
|
||||
FROM discuss_channel C
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM mail_message M
|
||||
WHERE M.res_id = C.id AND m.model = 'mail.channel'
|
||||
WHERE M.res_id = C.id AND m.model = 'discuss.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,))
|
||||
@@ -86,7 +86,7 @@ class MailChannel(models.Model):
|
||||
self.browse(empty_channel_ids).unlink()
|
||||
|
||||
def _execute_command_help_message_extra(self):
|
||||
msg = super(MailChannel, self)._execute_command_help_message_extra()
|
||||
msg = super()._execute_command_help_message_extra()
|
||||
if self.channel_type == 'livechat':
|
||||
return msg + _("Type <b>:shortcut</b> to insert a canned response in your message.<br>")
|
||||
return msg
|
||||
@@ -222,10 +222,10 @@ class MailChannel(models.Model):
|
||||
if self.chatbot_current_step_id:
|
||||
self.env['chatbot.message'].sudo().create({
|
||||
'mail_message_id': message.id,
|
||||
'mail_channel_id': self.id,
|
||||
'discuss_channel_id': self.id,
|
||||
'script_step_id': self.chatbot_current_step_id.id,
|
||||
})
|
||||
return super(MailChannel, self)._message_post_after_hook(message, msg_vals)
|
||||
return super()._message_post_after_hook(message, msg_vals)
|
||||
|
||||
def _chatbot_restart(self, chatbot_script):
|
||||
self.write({
|
||||
+3
-3
@@ -6,20 +6,20 @@ from odoo import api, models
|
||||
|
||||
|
||||
class ChannelMember(models.Model):
|
||||
_inherit = 'mail.channel.member'
|
||||
_inherit = 'discuss.channel.member'
|
||||
|
||||
@api.autovacuum
|
||||
def _gc_unpin_livechat_sessions(self):
|
||||
""" Unpin read livechat sessions with no activity for at least one day to
|
||||
clean the operator's interface """
|
||||
members = self.env['mail.channel.member'].search([
|
||||
members = self.env['discuss.channel.member'].search([
|
||||
('is_pinned', '=', True),
|
||||
('last_seen_dt', '<=', datetime.now() - timedelta(days=1)),
|
||||
('channel_id.channel_type', '=', 'livechat'),
|
||||
])
|
||||
sessions_to_be_unpinned = members.filtered(lambda m: m.message_unread_counter == 0)
|
||||
sessions_to_be_unpinned.write({'is_pinned': False})
|
||||
self.env['bus.bus']._sendmany([(member.partner_id, 'mail.channel/unpin', {'id': member.channel_id.id}) for member in sessions_to_be_unpinned])
|
||||
self.env['bus.bus']._sendmany([(member.partner_id, 'discuss.channel/unpin', {'id': member.channel_id.id}) for member in sessions_to_be_unpinned])
|
||||
|
||||
def _get_partner_data(self, fields=None):
|
||||
if self.channel_id.channel_type == 'livechat':
|
||||
@@ -56,7 +56,7 @@ class ImLivechatChannel(models.Model):
|
||||
|
||||
# relationnal fields
|
||||
user_ids = fields.Many2many('res.users', 'im_livechat_channel_im_user', 'channel_id', 'user_id', string='Operators', default=_default_user_ids)
|
||||
channel_ids = fields.One2many('mail.channel', 'livechat_channel_id', 'Sessions')
|
||||
channel_ids = fields.One2many('discuss.channel', 'livechat_channel_id', 'Sessions')
|
||||
chatbot_script_count = fields.Integer(string='Number of Chatbot', compute='_compute_chatbot_script_count')
|
||||
rule_ids = fields.One2many('im_livechat.channel.rule', 'channel_id', 'Rules')
|
||||
|
||||
@@ -87,7 +87,7 @@ class ImLivechatChannel(models.Model):
|
||||
|
||||
@api.depends('channel_ids')
|
||||
def _compute_nbr_channel(self):
|
||||
data = self.env['mail.channel']._read_group([
|
||||
data = self.env['discuss.channel']._read_group([
|
||||
('livechat_channel_id', 'in', self._ids),
|
||||
('has_message', '=', True)], ['livechat_channel_id'], ['__count'])
|
||||
channel_count = {livechat_channel.id: count for livechat_channel, count in data}
|
||||
@@ -137,8 +137,8 @@ class ImLivechatChannel(models.Model):
|
||||
self.ensure_one()
|
||||
return self.user_ids.filtered(lambda user: user.im_status == 'online')
|
||||
|
||||
def _get_livechat_mail_channel_vals(self, anonymous_name, operator=None, chatbot_script=None, user_id=None, country_id=None):
|
||||
# partner to add to the mail.channel
|
||||
def _get_livechat_discuss_channel_vals(self, anonymous_name, operator=None, chatbot_script=None, user_id=None, country_id=None):
|
||||
# partner to add to the discuss.channel
|
||||
operator_partner_id = operator.partner_id.id if operator else chatbot_script.operator_partner_id.id
|
||||
members_to_add = [Command.create({'partner_id': operator_partner_id, 'is_pinned': False})]
|
||||
visitor_user = False
|
||||
@@ -167,8 +167,8 @@ class ImLivechatChannel(models.Model):
|
||||
'name': name,
|
||||
}
|
||||
|
||||
def _open_livechat_mail_channel(self, anonymous_name, previous_operator_id=None, chatbot_script=None, user_id=None, country_id=None, persisted=True):
|
||||
""" Return a livechat session. If the session is persisted, creates a mail.channel record with a connected operator or with Odoobot as
|
||||
def _open_livechat_discuss_channel(self, anonymous_name, previous_operator_id=None, chatbot_script=None, user_id=None, country_id=None, persisted=True):
|
||||
""" Return a livechat session. If the session is persisted, creates a discuss.channel record with a connected operator or with Odoobot as
|
||||
an operator if a chatbot has been configured, or return false otherwise
|
||||
:param anonymous_name : the name of the anonymous person of the session
|
||||
:param previous_operator_id : partner_id.id of the previous operator that this visitor had in the past
|
||||
@@ -199,19 +199,19 @@ class ImLivechatChannel(models.Model):
|
||||
if not user_operator and not chatbot_script:
|
||||
# no one available
|
||||
return False
|
||||
mail_channel_vals = self._get_livechat_mail_channel_vals(anonymous_name, user_operator, chatbot_script, user_id=user_id, country_id=country_id)
|
||||
discuss_channel_vals = self._get_livechat_discuss_channel_vals(anonymous_name, user_operator, chatbot_script, user_id=user_id, country_id=country_id)
|
||||
if persisted:
|
||||
# create the session, and add the link with the given channel
|
||||
mail_channel = self.env["mail.channel"].with_context(mail_create_nosubscribe=False).sudo().create(mail_channel_vals)
|
||||
discuss_channel = self.env["discuss.channel"].with_context(mail_create_nosubscribe=False).sudo().create(discuss_channel_vals)
|
||||
if user_operator:
|
||||
mail_channel._broadcast([user_operator.partner_id.id])
|
||||
return mail_channel.sudo().channel_info()[0]
|
||||
discuss_channel._broadcast([user_operator.partner_id.id])
|
||||
return discuss_channel.sudo().channel_info()[0]
|
||||
else:
|
||||
operator_partner_id = user_operator.partner_id if user_operator else chatbot_script.operator_partner_id
|
||||
display_name = operator_partner_id.user_livechat_username or operator_partner_id.display_name
|
||||
return {
|
||||
'name': mail_channel_vals['name'],
|
||||
'chatbot_current_step_id': mail_channel_vals['chatbot_current_step_id'],
|
||||
'name': discuss_channel_vals['name'],
|
||||
'chatbot_current_step_id': discuss_channel_vals['chatbot_current_step_id'],
|
||||
'state': 'open',
|
||||
'operator_pid': (operator_partner_id.id, display_name.replace(',', '')),
|
||||
'chatbot_script_id': chatbot_script.id if chatbot_script else None
|
||||
@@ -222,7 +222,7 @@ class ImLivechatChannel(models.Model):
|
||||
A livechat is considered 'active' if it has at least one message within the 30 minutes.
|
||||
|
||||
(Some annoying conversions have to be made on the fly because this model holds 'res.users' as available operators
|
||||
and the mail_channel model stores the partner_id of the randomly selected operator)
|
||||
and the discuss_channel model stores the partner_id of the randomly selected operator)
|
||||
|
||||
:return : user
|
||||
:rtype : res.users
|
||||
@@ -232,8 +232,8 @@ class ImLivechatChannel(models.Model):
|
||||
return False
|
||||
|
||||
self.env.cr.execute("""SELECT COUNT(DISTINCT c.id), c.livechat_operator_id
|
||||
FROM mail_channel c
|
||||
LEFT OUTER JOIN mail_message m ON c.id = m.res_id AND m.model = 'mail.channel'
|
||||
FROM discuss_channel c
|
||||
LEFT OUTER JOIN mail_message m ON c.id = m.res_id AND m.model = 'discuss.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')
|
||||
|
||||
@@ -20,8 +20,8 @@ class MailMessage(models.Model):
|
||||
vals_list = super()._message_format(fnames=fnames, format_reply=format_reply, legacy=legacy)
|
||||
for vals in vals_list:
|
||||
message_sudo = self.browse(vals['id']).sudo().with_prefetch(self.ids)
|
||||
mail_channel = self.env['mail.channel'].browse(message_sudo.res_id) if message_sudo.model == 'mail.channel' else self.env['mail.channel']
|
||||
if mail_channel.channel_type == 'livechat':
|
||||
discuss_channel = self.env['discuss.channel'].browse(message_sudo.res_id) if message_sudo.model == 'discuss.channel' else self.env['discuss.channel']
|
||||
if discuss_channel.channel_type == 'livechat':
|
||||
if message_sudo.author_id:
|
||||
vals.pop('email_from')
|
||||
if message_sudo.author_id.user_livechat_username:
|
||||
@@ -29,8 +29,8 @@ class MailMessage(models.Model):
|
||||
'id': message_sudo.author_id.id,
|
||||
'user_livechat_username': message_sudo.author_id.user_livechat_username,
|
||||
}
|
||||
if mail_channel.chatbot_current_step_id \
|
||||
and message_sudo.author_id == mail_channel.chatbot_current_step_id.chatbot_script_id.operator_partner_id:
|
||||
if discuss_channel.chatbot_current_step_id \
|
||||
and message_sudo.author_id == discuss_channel.chatbot_current_step_id.chatbot_script_id.operator_partner_id:
|
||||
chatbot_message_id = self.env['chatbot.message'].sudo().search([
|
||||
('mail_message_id', '=', message_sudo.id)], limit=1)
|
||||
if chatbot_message_id.script_step_id:
|
||||
|
||||
@@ -13,7 +13,7 @@ class Rating(models.Model):
|
||||
for rating in self:
|
||||
# cannot change the rec_name of session since it is use to create the bus channel
|
||||
# so, need to override this method to set the same alternative rec_name as in reporting
|
||||
if rating.res_model == 'mail.channel':
|
||||
if rating.res_model == 'discuss.channel':
|
||||
current_object = self.env[rating.res_model].sudo().browse(rating.res_id)
|
||||
rating.res_name = ('%s / %s') % (current_object.livechat_channel_id.name, current_object.id)
|
||||
else:
|
||||
@@ -21,7 +21,7 @@ class Rating(models.Model):
|
||||
|
||||
def action_open_rated_object(self):
|
||||
action = super(Rating, self).action_open_rated_object()
|
||||
if self.res_model == 'mail.channel':
|
||||
view_id = self.env.ref('im_livechat.mail_channel_view_form').id
|
||||
if self.res_model == 'discuss.channel':
|
||||
view_id = self.env.ref('im_livechat.discuss_channel_view_form').id
|
||||
action['views'] = [[view_id, 'form']]
|
||||
return action
|
||||
|
||||
@@ -11,9 +11,9 @@ class Partners(models.Model):
|
||||
|
||||
def _get_channels_as_member(self):
|
||||
channels = super()._get_channels_as_member()
|
||||
channels |= self.env['mail.channel'].search([
|
||||
channels |= self.env['discuss.channel'].search([
|
||||
('channel_type', '=', 'livechat'),
|
||||
('channel_member_ids', 'in', self.env['mail.channel.member'].sudo()._search([
|
||||
('channel_member_ids', 'in', self.env['discuss.channel.member'].sudo()._search([
|
||||
('partner_id', '=', self.id),
|
||||
('is_pinned', '=', True),
|
||||
])),
|
||||
|
||||
@@ -13,7 +13,7 @@ class ImLivechatReportChannel(models.Model):
|
||||
_auto = False
|
||||
|
||||
uuid = fields.Char('UUID', readonly=True)
|
||||
channel_id = fields.Many2one('mail.channel', 'Conversation', readonly=True)
|
||||
channel_id = fields.Many2one('discuss.channel', 'Conversation', readonly=True)
|
||||
channel_name = fields.Char('Channel Name', readonly=True)
|
||||
technical_name = fields.Char('Code', readonly=True)
|
||||
livechat_channel_id = fields.Many2one('im_livechat.channel', 'Channel', readonly=True)
|
||||
@@ -62,7 +62,7 @@ class ImLivechatReportChannel(models.Model):
|
||||
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 M.model = 'discuss.channel'
|
||||
AND C.livechat_operator_id = M.author_id)
|
||||
THEN 0
|
||||
ELSE 1
|
||||
@@ -89,11 +89,11 @@ class ImLivechatReportChannel(models.Model):
|
||||
ELSE 1
|
||||
END as is_unrated,
|
||||
C.livechat_operator_id as partner_id
|
||||
FROM mail_channel C
|
||||
JOIN mail_message M ON (M.res_id = C.id AND M.model = 'mail.channel')
|
||||
FROM discuss_channel C
|
||||
JOIN mail_message M ON (M.res_id = C.id AND M.model = 'discuss.channel')
|
||||
JOIN im_livechat_channel L ON (L.id = C.livechat_channel_id)
|
||||
LEFT JOIN mail_message MO ON (MO.res_id = C.id AND MO.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')
|
||||
LEFT JOIN mail_message MO ON (MO.res_id = C.id AND MO.model = 'discuss.channel' AND MO.author_id = C.livechat_operator_id)
|
||||
LEFT JOIN rating_rating Rate ON (Rate.res_id = C.id and Rate.res_model = 'discuss.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
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ class ImLivechatReportOperator(models.Model):
|
||||
partner_id = fields.Many2one('res.partner', 'Operator', readonly=True)
|
||||
livechat_channel_id = fields.Many2one('im_livechat.channel', 'Channel', readonly=True)
|
||||
nbr_channel = fields.Integer('# of Sessions', readonly=True, group_operator="sum")
|
||||
channel_id = fields.Many2one('mail.channel', 'Conversation', readonly=True)
|
||||
channel_id = fields.Many2one('discuss.channel', 'Conversation', readonly=True)
|
||||
start_date = fields.Datetime('Start Date of session', readonly=True)
|
||||
time_to_answer = fields.Float('Time to answer', digits=(16, 2), readonly=True, group_operator="avg", help="Average time to give the first answer to the visitor")
|
||||
duration = fields.Float('Average duration', digits=(16, 2), readonly=True, group_operator="avg", help="Duration of the conversation (in seconds)")
|
||||
@@ -34,9 +34,9 @@ class ImLivechatReportOperator(models.Model):
|
||||
C.create_date AS start_date,
|
||||
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 M ON M.res_id = C.id AND M.model = 'mail.channel'
|
||||
LEFT JOIN mail_message MO ON (MO.res_id = C.id AND MO.model = 'mail.channel' AND MO.author_id = C.livechat_operator_id)
|
||||
FROM discuss_channel C
|
||||
JOIN mail_message M ON M.res_id = C.id AND M.model = 'discuss.channel'
|
||||
LEFT JOIN mail_message MO ON (MO.res_id = C.id AND MO.model = 'discuss.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
|
||||
)
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
</record>
|
||||
|
||||
<data noupdate="1">
|
||||
<record id="im_livechat_rule_manager_read_all_mail_channel" model="ir.rule">
|
||||
<record id="im_livechat_rule_manager_read_all_discuss_channel" model="ir.rule">
|
||||
<field name="name">Livechat: Administrator: read all livechat channel</field>
|
||||
<field name="model_id" ref="model_mail_channel"/>
|
||||
<field name="model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="groups" eval="[(4, ref('im_livechat_group_manager'))]"/>
|
||||
<field name="domain_force">[('channel_type', '=', 'livechat')]</field>
|
||||
<field name="perm_read" eval="True"/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("mail.channel_commands").add("history", {
|
||||
registry.category("discuss.channel_commands").add("history", {
|
||||
channel_types: ["livechat"],
|
||||
help: _t("See 15 last visited pages"),
|
||||
methodName: "execute_command_history",
|
||||
|
||||
@@ -14,7 +14,7 @@ patch(Messaging.prototype, "im_livechat", {
|
||||
|
||||
_handleNotificationLastInterestDtChanged(notif) {
|
||||
this._super(notif);
|
||||
const channel = this.store.threads[createLocalId("mail.channel", notif.payload.id)];
|
||||
const channel = this.store.threads[createLocalId("discuss.channel", notif.payload.id)];
|
||||
if (channel?.type === "livechat") {
|
||||
this.threadService.sortChannels();
|
||||
}
|
||||
|
||||
@@ -62,9 +62,9 @@ LivechatButton.include({
|
||||
* (See chatbot.script#_get_welcome_steps() for more details).
|
||||
*
|
||||
* It is important that those messages are sent as "welcome messages", meaning manually added
|
||||
* within the template, without creating actual mail.messages in the mail.channel.
|
||||
* within the template, without creating actual mail.messages in the discuss.channel.
|
||||
*
|
||||
* Indeed, if the end-user never interacts with the bot, those empty mail.channels are deleted
|
||||
* Indeed, if the end-user never interacts with the bot, those empty discuss.channels are deleted
|
||||
* by a garbage collector mechanism.
|
||||
*
|
||||
* About "welcomeMessageDelay":
|
||||
@@ -72,7 +72,7 @@ LivechatButton.include({
|
||||
* The first time we open the chat, we want to bot to slowly input those messages in one at a
|
||||
* time, with pauses during which the end-user sees ("The bot is typing...").
|
||||
*
|
||||
* However, if the user navigates within the website (meaning he has an opened mail.channel),
|
||||
* However, if the user navigates within the website (meaning he has an opened discuss.channel),
|
||||
* then we input all the welcome messages at once without pauses, to avoid having that annoying
|
||||
* slow effect on every page / refresh.
|
||||
*
|
||||
@@ -96,7 +96,7 @@ LivechatButton.include({
|
||||
chatbot_script_step_id: chatbotStep.chatbot_script_step_id,
|
||||
chatbot_step_answers: chatbotStep.chatbot_step_answers,
|
||||
date: time.datetime_to_str(new Date()),
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
message_type: "comment",
|
||||
res_id: this.messaging.publicLivechatGlobal.publicLivechat.id,
|
||||
});
|
||||
|
||||
@@ -127,7 +127,7 @@ Model({
|
||||
},
|
||||
/**
|
||||
* Called when the visitor leaves the livechat chatter the first time (first click on X button)
|
||||
* this will deactivate the mail_channel, notify operator that visitor has left the channel.
|
||||
* this will deactivate the discuss_channel, notify operator that visitor has left the channel.
|
||||
*/
|
||||
leaveSession() {
|
||||
const cookie = getCookie("im_livechat_session");
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ Model({
|
||||
});
|
||||
return;
|
||||
}
|
||||
case "mail.channel.member/typing_status": {
|
||||
case "discuss.channel.member/typing_status": {
|
||||
if (
|
||||
!this.messaging.publicLivechatGlobal.chatWindow ||
|
||||
!this.messaging.publicLivechatGlobal.chatWindow.exists()
|
||||
@@ -75,7 +75,7 @@ Model({
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "mail.channel/new_message": {
|
||||
case "discuss.channel/new_message": {
|
||||
if (
|
||||
!this.messaging.publicLivechatGlobal.chatWindow ||
|
||||
!this.messaging.publicLivechatGlobal.chatWindow.exists()
|
||||
|
||||
@@ -64,7 +64,7 @@ const LivechatButton = Widget.extend({
|
||||
},
|
||||
body: this.messaging.publicLivechatGlobal.livechatButtonView.defaultMessage,
|
||||
date: time.datetime_to_str(new Date()),
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
res_id: this.messaging.publicLivechatGlobal.publicLivechat.id,
|
||||
},
|
||||
{ prepend: true }
|
||||
|
||||
+1
-1
@@ -432,7 +432,7 @@ const PublicLivechatView = Widget.extend({
|
||||
ev.preventDefault();
|
||||
const model = $(ev.target).data("oe-model");
|
||||
let options;
|
||||
if (model && model !== "mail.channel") {
|
||||
if (model && model !== "discuss.channel") {
|
||||
options = {
|
||||
model,
|
||||
id,
|
||||
|
||||
@@ -6,7 +6,7 @@ QUnit.module("chat window (patch)");
|
||||
|
||||
QUnit.test("No call buttons", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -27,7 +27,7 @@ QUnit.test("closing a chat window with no message from admin side unpins it", as
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Demo" });
|
||||
pyEnv["res.users"].create({ partner_id: partnerId });
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[
|
||||
0,
|
||||
@@ -46,7 +46,7 @@ QUnit.test("closing a chat window with no message from admin side unpins it", as
|
||||
await click(".o_menu_systray i[aria-label='Messages']");
|
||||
await click(".o-mail-NotificationItem");
|
||||
await click(".o-mail-ChatWindow-header .o-mail-ChatWindow-command[title='Close chat window']");
|
||||
const channels = await env.services.orm.silent.call("mail.channel", "channel_info", [
|
||||
const channels = await env.services.orm.silent.call("discuss.channel", "channel_info", [
|
||||
channelId,
|
||||
]);
|
||||
assert.strictEqual(channels[0].is_pinned, false, "Livechat channel should not be pinned");
|
||||
|
||||
@@ -14,7 +14,7 @@ QUnit.module("composer (patch)");
|
||||
|
||||
QUnit.test("No add attachments button", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "Livechat 1",
|
||||
channel_type: "livechat",
|
||||
});
|
||||
@@ -28,7 +28,7 @@ QUnit.test("Attachment upload via drag and drop disabled", async (assert) => {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "Livechat 1",
|
||||
channel_type: "livechat",
|
||||
});
|
||||
@@ -42,7 +42,7 @@ QUnit.test("Attachment upload via drag and drop disabled", async (assert) => {
|
||||
|
||||
QUnit.test("Can execute help command on livechat channels", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -70,7 +70,7 @@ QUnit.test("Can execute help command on livechat channels", async (assert) => {
|
||||
|
||||
QUnit.test('Receives visitor typing status "is typing"', async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 20",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -82,7 +82,7 @@ QUnit.test('Receives visitor typing status "is typing"', async (assert) => {
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.strictEqual($(".o-mail-Typing").text(), "");
|
||||
const channel = pyEnv["mail.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
const channel = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
// simulate receive typing notification from livechat visitor "is typing"
|
||||
await afterNextRender(() =>
|
||||
env.services.rpc("/im_livechat/notify_typing", {
|
||||
@@ -96,7 +96,7 @@ QUnit.test('Receives visitor typing status "is typing"', async (assert) => {
|
||||
|
||||
QUnit.test('display canned response suggestions on typing ":"', async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Mario",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -118,7 +118,7 @@ QUnit.test('display canned response suggestions on typing ":"', async (assert) =
|
||||
|
||||
QUnit.test("use a canned response", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Mario",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -147,7 +147,7 @@ QUnit.test("use a canned response", async (assert) => {
|
||||
|
||||
QUnit.test("use a canned response some text", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Mario",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -178,7 +178,7 @@ QUnit.test("use a canned response some text", async (assert) => {
|
||||
|
||||
QUnit.test("add an emoji after a canned response", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 20",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
|
||||
@@ -12,7 +12,7 @@ QUnit.module("discuss (patch)");
|
||||
|
||||
QUnit.test("No call buttons", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -29,7 +29,7 @@ QUnit.test("No call buttons", async (assert) => {
|
||||
|
||||
QUnit.test("No reaction button", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
@@ -37,7 +37,7 @@ QUnit.test("No reaction button", async (assert) => {
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
@@ -48,7 +48,7 @@ QUnit.test("No reaction button", async (assert) => {
|
||||
|
||||
QUnit.test("No reply button", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
@@ -56,7 +56,7 @@ QUnit.test("No reply button", async (assert) => {
|
||||
});
|
||||
pyEnv["mail.message"].create({
|
||||
body: "not empty",
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
res_id: channelId,
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
@@ -72,7 +72,7 @@ QUnit.test("add livechat in the sidebar on visitor sending first message", async
|
||||
const livechatChannelId = pyEnv["im_livechat.channel"].create({
|
||||
user_ids: [pyEnv.currentUserId],
|
||||
});
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor (Belgium)",
|
||||
channel_member_ids: [
|
||||
[0, 0, { is_pinned: false, partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -87,7 +87,7 @@ QUnit.test("add livechat in the sidebar on visitor sending first message", async
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussCategory-livechat");
|
||||
// simulate livechat visitor sending a message
|
||||
const [channel] = pyEnv["mail.channel"].searchRead([["id", "=", channelId]]);
|
||||
const [channel] = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]]);
|
||||
await afterNextRender(async () =>
|
||||
env.services.rpc("/mail/chat_post", {
|
||||
context: { mockedUserId: false },
|
||||
@@ -105,7 +105,7 @@ QUnit.test("add livechat in the sidebar on visitor sending first message", async
|
||||
|
||||
QUnit.test("reaction button should not be present on livechat", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_type: "livechat",
|
||||
livechat_operator_id: pyEnv.currentPartnerId,
|
||||
@@ -121,7 +121,7 @@ QUnit.test("reaction button should not be present on livechat", async (assert) =
|
||||
|
||||
QUnit.test("invite button should be present on livechat", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -139,7 +139,7 @@ QUnit.test(
|
||||
"livechats are sorted by last activity time in the sidebar: most recent at the top",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create([
|
||||
pyEnv["discuss.channel"].create([
|
||||
{
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
|
||||
@@ -60,7 +60,7 @@ patch(MockServer.prototype, "im_livechat/controllers/main", {
|
||||
anonymous_name = anonymous_name + " (" + country.name + ")";
|
||||
}
|
||||
}
|
||||
return this._mockImLivechatChannel_openLivechatMailChannel(
|
||||
return this._mockImLivechatChannel_openLivechatDiscussChannel(
|
||||
channel_id,
|
||||
anonymous_name,
|
||||
previous_operator_id,
|
||||
@@ -77,12 +77,12 @@ patch(MockServer.prototype, "im_livechat/controllers/main", {
|
||||
* @param {Object} [context={}]
|
||||
*/
|
||||
_mockRouteImLivechatNotifyTyping(uuid, is_typing, context = {}) {
|
||||
const [mailChannel] = this.getRecords("mail.channel", [["uuid", "=", uuid]]);
|
||||
const [discussChannel] = this.getRecords("discuss.channel", [["uuid", "=", uuid]]);
|
||||
const partnerId = context.mockedPartnerId || this.currentPartnerId;
|
||||
const [memberOfCurrentUser] = this.getRecords("mail.channel.member", [
|
||||
["channel_id", "=", mailChannel.id],
|
||||
const [memberOfCurrentUser] = this.getRecords("discuss.channel.member", [
|
||||
["channel_id", "=", discussChannel.id],
|
||||
["partner_id", "=", partnerId],
|
||||
]);
|
||||
this._mockMailChannelMember_NotifyTyping([memberOfCurrentUser.id], is_typing);
|
||||
this._mockDiscussChannelMember_NotifyTyping([memberOfCurrentUser.id], is_typing);
|
||||
},
|
||||
});
|
||||
|
||||
+4
-4
@@ -1,18 +1,18 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import "@mail/../tests/helpers/mock_server/models/mail_channel"; // ensure mail overrides are applied first
|
||||
import "@mail/../tests/helpers/mock_server/models/discuss_channel"; // ensure mail overrides are applied first
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { MockServer } from "@web/../tests/helpers/mock_server";
|
||||
|
||||
patch(MockServer.prototype, "im_livechat/models/mail_channel", {
|
||||
patch(MockServer.prototype, "im_livechat/models/discuss_channel", {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_mockMailChannelChannelInfo(ids) {
|
||||
_mockDiscussChannelChannelInfo(ids) {
|
||||
const channelInfos = this._super(...arguments);
|
||||
for (const channelInfo of channelInfos) {
|
||||
const channel = this.getRecords("mail.channel", [["id", "=", channelInfo.id]])[0];
|
||||
const channel = this.getRecords("discuss.channel", [["id", "=", channelInfo.id]])[0];
|
||||
channelInfo["channel"]["anonymous_name"] = channel.anonymous_name;
|
||||
// add the last message date
|
||||
if (channel.channel_type === "livechat") {
|
||||
+5
-5
@@ -1,17 +1,17 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import "@mail/../tests/helpers/mock_server/models/mail_channel_member"; // ensure mail overrides are applied first
|
||||
import "@mail/../tests/helpers/mock_server/models/discuss_channel_member"; // ensure mail overrides are applied first
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { MockServer } from "@web/../tests/helpers/mock_server";
|
||||
|
||||
patch(MockServer.prototype, "im_livechat/models/mail_channel_member", {
|
||||
patch(MockServer.prototype, "im_livechat/models/discuss_channel_member", {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_mockMailChannelMember_GetPartnerData(ids) {
|
||||
const [member] = this.getRecords("mail.channel.member", [["id", "in", ids]]);
|
||||
const [channel] = this.getRecords("mail.channel", [["id", "=", member.channel_id]]);
|
||||
_mockDiscussChannelMember_GetPartnerData(ids) {
|
||||
const [member] = this.getRecords("discuss.channel.member", [["id", "in", ids]]);
|
||||
const [channel] = this.getRecords("discuss.channel", [["id", "=", member.channel_id]]);
|
||||
const [partner] = this.getRecords("res.partner", [["id", "=", member.partner_id]], {
|
||||
active_test: false,
|
||||
});
|
||||
@@ -17,20 +17,20 @@ patch(MockServer.prototype, "im_livechat/models/im_livechat_channel", {
|
||||
return users.filter((user) => user.im_status === "online");
|
||||
},
|
||||
/**
|
||||
* Simulates `_get_livechat_mail_channel_vals` on `im_livechat.channel`.
|
||||
* Simulates `_get_livechat_discuss_channel_vals` on `im_livechat.channel`.
|
||||
*
|
||||
* @private
|
||||
* @param {integer} id
|
||||
* @returns {Object}
|
||||
*/
|
||||
_mockImLivechatChannel_getLivechatMailChannelVals(
|
||||
_mockImLivechatChannel_getLivechatDiscussChannelVals(
|
||||
id,
|
||||
anonymous_name,
|
||||
operator,
|
||||
user_id,
|
||||
country_id
|
||||
) {
|
||||
// partner to add to the mail.channel
|
||||
// partner to add to the discuss.channel
|
||||
const operator_partner_id = operator.partner_id;
|
||||
const membersToAdd = [
|
||||
[
|
||||
@@ -80,7 +80,7 @@ patch(MockServer.prototype, "im_livechat/models/im_livechat_channel", {
|
||||
return availableUsers[0];
|
||||
},
|
||||
/**
|
||||
* Simulates `_open_livechat_mail_channel` on `im_livechat.channel`.
|
||||
* Simulates `_open_livechat_discuss_channel` on `im_livechat.channel`.
|
||||
*
|
||||
* @private
|
||||
* @param {integer} id
|
||||
@@ -90,7 +90,7 @@ patch(MockServer.prototype, "im_livechat/models/im_livechat_channel", {
|
||||
* @param {integer} [country_id]
|
||||
* @returns {Object}
|
||||
*/
|
||||
_mockImLivechatChannel_openLivechatMailChannel(
|
||||
_mockImLivechatChannel_openLivechatDiscussChannel(
|
||||
id,
|
||||
anonymous_name,
|
||||
previous_operator_id,
|
||||
@@ -110,15 +110,15 @@ patch(MockServer.prototype, "im_livechat/models/im_livechat_channel", {
|
||||
return false;
|
||||
}
|
||||
// create the session, and add the link with the given channel
|
||||
const mailChannelVals = this._mockImLivechatChannel_getLivechatMailChannelVals(
|
||||
const discussChannelVals = this._mockImLivechatChannel_getLivechatDiscussChannelVals(
|
||||
id,
|
||||
anonymous_name,
|
||||
operator,
|
||||
user_id,
|
||||
country_id
|
||||
);
|
||||
const mailChannelId = this.pyEnv["mail.channel"].create(mailChannelVals);
|
||||
this._mockMailChannel_broadcast([mailChannelId], [operator.partner_id]);
|
||||
return this._mockMailChannelChannelInfo([mailChannelId])[0];
|
||||
const discussChannelId = this.pyEnv["discuss.channel"].create(discussChannelVals);
|
||||
this._mockDiscussChannel_broadcast([discussChannelId], [operator.partner_id]);
|
||||
return this._mockDiscussChannelChannelInfo([discussChannelId])[0];
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,11 +11,11 @@ patch(MockServer.prototype, "im_livechat/models/res_partner", {
|
||||
*/
|
||||
_mockResPartner_GetChannelsAsMember(ids) {
|
||||
const partner = this.getRecords("res.partner", [["id", "in", ids]])[0];
|
||||
const members = this.getRecords("mail.channel.member", [
|
||||
const members = this.getRecords("discuss.channel.member", [
|
||||
["partner_id", "=", partner.id],
|
||||
["is_pinned", "=", true],
|
||||
]);
|
||||
const livechats = this.getRecords("mail.channel", [
|
||||
const livechats = this.getRecords("discuss.channel", [
|
||||
["channel_type", "=", "livechat"],
|
||||
["channel_member_ids", "in", members.map((member) => member.id)],
|
||||
]);
|
||||
|
||||
@@ -6,7 +6,7 @@ QUnit.module("messaging menu (patch)");
|
||||
|
||||
QUnit.test('livechats should be in "chat" filter', async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
|
||||
@@ -11,11 +11,11 @@ QUnit.module("messaging service (patch)");
|
||||
QUnit.test("Notify message received out of focus", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const senderId = pyEnv["res.users"].create({ name: "Bob" });
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
name: "Livechat 1",
|
||||
channel_type: "livechat",
|
||||
});
|
||||
const [channel] = pyEnv["mail.channel"].searchRead([["id", "=", channelId]]);
|
||||
const [channel] = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]]);
|
||||
const { env } = await start({
|
||||
services: {
|
||||
notification: makeFakeNotificationService((message, { title }) => {
|
||||
|
||||
@@ -20,7 +20,7 @@ QUnit.test(
|
||||
"Livechat button is present when there is at least one livechat thread",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
|
||||
@@ -9,7 +9,7 @@ QUnit.module("discuss sidebar (patch)");
|
||||
|
||||
QUnit.test("Unknown visitor", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -34,7 +34,7 @@ QUnit.test("Known user with country", async (assert) => {
|
||||
country_id: countryId,
|
||||
name: "Jean",
|
||||
});
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: partnerId }],
|
||||
@@ -53,7 +53,7 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
|
||||
const livechatChannelId = pyEnv["im_livechat.channel"].create({
|
||||
user_ids: [pyEnv.currentUserId],
|
||||
});
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[
|
||||
0,
|
||||
@@ -73,7 +73,7 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
|
||||
await openDiscuss();
|
||||
assert.containsNone($, ".o-mail-DiscussCategory-livechat");
|
||||
// simulate livechat visitor typing
|
||||
const channel = pyEnv["mail.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
const channel = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
await env.services.rpc("/im_livechat/notify_typing", {
|
||||
context: {
|
||||
mockedPartnerId: pyEnv.publicPartnerId,
|
||||
@@ -87,7 +87,7 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
|
||||
|
||||
QUnit.test("Close should update the value on the server", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -120,7 +120,7 @@ QUnit.test("Close should update the value on the server", async (assert) => {
|
||||
|
||||
QUnit.test("Open should update the value on the server", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -153,7 +153,7 @@ QUnit.test("Open should update the value on the server", async (assert) => {
|
||||
|
||||
QUnit.test("Open from the bus", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -182,7 +182,7 @@ QUnit.test("Open from the bus", async (assert) => {
|
||||
|
||||
QUnit.test("Close from the bus", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -211,7 +211,7 @@ QUnit.test("Close from the bus", async (assert) => {
|
||||
|
||||
QUnit.test("Smiley face avatar for an anonymous livechat item", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -231,7 +231,7 @@ QUnit.test("Smiley face avatar for an anonymous livechat item", async (assert) =
|
||||
QUnit.test("Partner profile picture for livechat item linked to a partner", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Jean" });
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: partnerId }],
|
||||
@@ -249,7 +249,7 @@ QUnit.test("Partner profile picture for livechat item linked to a partner", asyn
|
||||
|
||||
QUnit.test("No counter if the category is unfolded and with unread messages", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[
|
||||
@@ -276,7 +276,7 @@ QUnit.test("No counter if the category is unfolded and with unread messages", as
|
||||
|
||||
QUnit.test("No counter if category is folded and without unread messages", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -302,7 +302,7 @@ QUnit.test(
|
||||
"Counter should have correct value of unread threads if category is folded and with unread messages",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[
|
||||
@@ -333,7 +333,7 @@ QUnit.test(
|
||||
|
||||
QUnit.test("Close manually by clicking the title", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -360,7 +360,7 @@ QUnit.test("Close manually by clicking the title", async (assert) => {
|
||||
|
||||
QUnit.test("Open manually by clicking the title", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -387,7 +387,7 @@ QUnit.test("Open manually by clicking the title", async (assert) => {
|
||||
|
||||
QUnit.test("Category item should be invisible if the category is closed", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -407,7 +407,7 @@ QUnit.test(
|
||||
"Active category item should be visible even if the category is closed",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -431,7 +431,7 @@ QUnit.test(
|
||||
|
||||
QUnit.test("Clicking on unpin button unpins the channel", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
pyEnv["mail.channel"].create({
|
||||
pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -454,7 +454,7 @@ QUnit.test("Message unread counter", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Harry" });
|
||||
const userId = pyEnv["res.users"].create({ name: "Harry", partner_id: partnerId });
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 11",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -469,7 +469,7 @@ QUnit.test("Message unread counter", async (assert) => {
|
||||
env.services.rpc("/mail/chat_post", {
|
||||
context: { mockedUserId: userId },
|
||||
message_content: "hu",
|
||||
uuid: pyEnv["mail.channel"].searchRead([["id", "=", channelId]])[0].uuid,
|
||||
uuid: pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0].uuid,
|
||||
})
|
||||
);
|
||||
assert.containsOnce($, ".o-mail-DiscussCategoryItem .badge:contains(1)");
|
||||
|
||||
@@ -6,7 +6,7 @@ QUnit.module("thread icon (patch)");
|
||||
|
||||
QUnit.test("Public website visitor is typing", async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const channelId = pyEnv["mail.channel"].create({
|
||||
const channelId = pyEnv["discuss.channel"].create({
|
||||
anonymous_name: "Visitor 20",
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
@@ -18,7 +18,7 @@ QUnit.test("Public website visitor is typing", async (assert) => {
|
||||
const { env, openDiscuss } = await start();
|
||||
await openDiscuss(channelId);
|
||||
assert.containsOnce($, ".o-mail-ThreadIcon .fa.fa-comments");
|
||||
const channel = pyEnv["mail.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
const channel = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0];
|
||||
// simulate receive typing notification from livechat visitor "is typing"
|
||||
await afterNextRender(() =>
|
||||
env.services.rpc("/im_livechat/notify_typing", {
|
||||
|
||||
@@ -5,7 +5,7 @@ from . import chatbot_common
|
||||
from . import test_chatbot_form_ui
|
||||
from . import test_chatbot_internals
|
||||
from . import test_digest
|
||||
from . import test_get_mail_channel
|
||||
from . import test_get_discuss_channel
|
||||
from . import test_im_livechat_report
|
||||
from . import test_im_livechat_support_page
|
||||
from . import test_message
|
||||
|
||||
@@ -134,12 +134,12 @@ class ChatbotCase(common.TransactionCase):
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def _post_answer_and_trigger_next_step(cls, mail_channel, answer, chatbot_script_answer=False):
|
||||
mail_message = mail_channel.message_post(body=answer)
|
||||
def _post_answer_and_trigger_next_step(cls, discuss_channel, answer, chatbot_script_answer=False):
|
||||
mail_message = discuss_channel.message_post(body=answer)
|
||||
if chatbot_script_answer:
|
||||
cls.env['chatbot.message'].search([
|
||||
('mail_message_id', '=', mail_message.id)
|
||||
], limit=1).user_script_answer_id = chatbot_script_answer.id
|
||||
|
||||
next_step = mail_channel.chatbot_current_step_id._process_answer(mail_channel, mail_message.body)
|
||||
next_step._process_step(mail_channel)
|
||||
next_step = discuss_channel.chatbot_current_step_id._process_answer(discuss_channel, mail_message.body)
|
||||
next_step._process_step(discuss_channel)
|
||||
|
||||
@@ -44,24 +44,24 @@ class ChatbotCase(chatbot_common.ChatbotCase):
|
||||
"Only step 'step_no_one_available' should be flagged as forward operator child.")
|
||||
|
||||
def test_chatbot_steps(self):
|
||||
channel_info = self.livechat_channel._open_livechat_mail_channel(
|
||||
channel_info = self.livechat_channel._open_livechat_discuss_channel(
|
||||
anonymous_name='Test Visitor', chatbot_script=self.chatbot_script)
|
||||
mail_channel = self.env['mail.channel'].browse(channel_info['id'])
|
||||
discuss_channel = self.env['discuss.channel'].browse(channel_info['id'])
|
||||
|
||||
self.assertEqual(mail_channel.chatbot_current_step_id, self.step_dispatch)
|
||||
self.assertEqual(discuss_channel.chatbot_current_step_id, self.step_dispatch)
|
||||
|
||||
self._post_answer_and_trigger_next_step(
|
||||
mail_channel,
|
||||
discuss_channel,
|
||||
self.step_dispatch_buy_software.name,
|
||||
chatbot_script_answer=self.step_dispatch_buy_software
|
||||
)
|
||||
self.assertEqual(mail_channel.chatbot_current_step_id, self.step_email)
|
||||
self.assertEqual(discuss_channel.chatbot_current_step_id, self.step_email)
|
||||
|
||||
with self.assertRaises(ValidationError, msg="Should raise an error since it's not a valid email"):
|
||||
self._post_answer_and_trigger_next_step(mail_channel, 'test')
|
||||
self._post_answer_and_trigger_next_step(discuss_channel, 'test')
|
||||
|
||||
self._post_answer_and_trigger_next_step(mail_channel, 'test@example.com')
|
||||
self.assertEqual(mail_channel.chatbot_current_step_id, self.step_email_validated)
|
||||
self._post_answer_and_trigger_next_step(discuss_channel, 'test@example.com')
|
||||
self.assertEqual(discuss_channel.chatbot_current_step_id, self.step_email_validated)
|
||||
|
||||
def test_chatbot_steps_sequence(self):
|
||||
""" Ensure sequence is correct when creating chatbots and adding steps to an existing one.
|
||||
|
||||
@@ -16,7 +16,7 @@ class TestLiveChatDigest(TestDigestCommon):
|
||||
|
||||
other_partner = cls.env['res.partner'].create({'name': 'Other Partner'})
|
||||
|
||||
cls.channels = cls.env['mail.channel'].create([{
|
||||
cls.channels = cls.env['discuss.channel'].create([{
|
||||
'name': 'Channel 1',
|
||||
'livechat_operator_id': cls.env.user.partner_id.id,
|
||||
'channel_type': 'livechat',
|
||||
@@ -35,25 +35,25 @@ class TestLiveChatDigest(TestDigestCommon):
|
||||
cls.env['rating.rating'].create([{
|
||||
'rated_partner_id': cls.env.user.partner_id.id,
|
||||
'res_id': cls.channels[0].id,
|
||||
'res_model_id': cls.env['ir.model']._get('mail.channel').id,
|
||||
'res_model_id': cls.env['ir.model']._get('discuss.channel').id,
|
||||
'consumed': True,
|
||||
'rating': 5,
|
||||
}, {
|
||||
'rated_partner_id': cls.env.user.partner_id.id,
|
||||
'res_id': cls.channels[0].id,
|
||||
'res_model_id': cls.env['ir.model']._get('mail.channel').id,
|
||||
'res_model_id': cls.env['ir.model']._get('discuss.channel').id,
|
||||
'consumed': True,
|
||||
'rating': 0,
|
||||
}, {
|
||||
'rated_partner_id': cls.env.user.partner_id.id,
|
||||
'res_id': cls.channels[0].id,
|
||||
'res_model_id': cls.env['ir.model']._get('mail.channel').id,
|
||||
'res_model_id': cls.env['ir.model']._get('discuss.channel').id,
|
||||
'consumed': True,
|
||||
'rating': 3,
|
||||
}, {
|
||||
'rated_partner_id': cls.env.user.partner_id.id,
|
||||
'res_id': cls.channels[0].id,
|
||||
'res_model_id': cls.env['ir.model']._get('mail.channel').id,
|
||||
'res_model_id': cls.env['ir.model']._get('discuss.channel').id,
|
||||
'consumed': True,
|
||||
'rating': 3,
|
||||
}])
|
||||
|
||||
+27
-27
@@ -7,15 +7,15 @@ from odoo import fields
|
||||
from odoo.addons.im_livechat.tests.common import TestImLivechatCommon
|
||||
|
||||
|
||||
class TestGetMailChannel(TestImLivechatCommon):
|
||||
def test_get_mail_channel(self):
|
||||
class TestGetDiscussChannel(TestImLivechatCommon):
|
||||
def test_get_discuss_channel(self):
|
||||
"""For a livechat with 5 available operators, we open 5 channels 5 times (25 channels total).
|
||||
For every 5 channels opening, we check that all operators were assigned.
|
||||
"""
|
||||
|
||||
for i in range(5):
|
||||
mail_channels = self._open_livechat_mail_channel()
|
||||
channel_operators = [channel_info['operator_pid'] for channel_info in mail_channels]
|
||||
discuss_channels = self._open_livechat_discuss_channel()
|
||||
channel_operators = [channel_info['operator_pid'] for channel_info in discuss_channels]
|
||||
channel_operator_ids = [channel_operator[0] for channel_operator in channel_operators]
|
||||
self.assertTrue(all(partner_id in channel_operator_ids for partner_id in self.operators.mapped('partner_id').ids))
|
||||
|
||||
@@ -26,7 +26,7 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
|
||||
# ensure visitor info are correct with anonymous
|
||||
operator = self.operators[0]
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_mail_channel(anonymous_name='Visitor 22', previous_operator_id=operator.partner_id.id, country_id=belgium.id)
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_discuss_channel(anonymous_name='Visitor 22', previous_operator_id=operator.partner_id.id, country_id=belgium.id)
|
||||
self.assertEqual(channel_info['channel']['anonymous_name'], "Visitor 22")
|
||||
self.assertEqual(channel_info['channel']['anonymous_country'], {'code': 'BE', 'id': belgium.id, 'name': 'Belgium'})
|
||||
|
||||
@@ -46,13 +46,13 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
}], key=lambda m: m['id']))
|
||||
|
||||
# ensure visitor info are correct with real user
|
||||
channel_info = self.livechat_channel.with_user(test_user)._open_livechat_mail_channel(anonymous_name='whatever', previous_operator_id=operator.partner_id.id, user_id=test_user.id)
|
||||
channel_info = self.livechat_channel.with_user(test_user)._open_livechat_discuss_channel(anonymous_name='whatever', previous_operator_id=operator.partner_id.id, user_id=test_user.id)
|
||||
self.assertFalse(channel_info['channel']['anonymous_name'])
|
||||
self.assertEqual(channel_info['channel']['anonymous_country'], [('clear',)])
|
||||
self.assertEqual(channel_info['channel']['channelMembers'], [('insert', [
|
||||
{
|
||||
'channel': {'id': channel_info['id']},
|
||||
'id': self.env['mail.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', '=', operator.partner_id.id)]).id,
|
||||
'id': self.env['discuss.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', '=', operator.partner_id.id)]).id,
|
||||
'persona': {
|
||||
'partner': {
|
||||
'active': True,
|
||||
@@ -65,7 +65,7 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
},
|
||||
{
|
||||
'channel': {'id': channel_info['id']},
|
||||
'id': self.env['mail.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', '=', test_user.partner_id.id)]).id,
|
||||
'id': self.env['discuss.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', '=', test_user.partner_id.id)]).id,
|
||||
'persona': {
|
||||
'partner': {
|
||||
'active': True,
|
||||
@@ -84,14 +84,14 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
|
||||
# ensure visitor info are correct when operator is testing themselves
|
||||
operator = self.operators[0]
|
||||
channel_info = self.livechat_channel.with_user(operator)._open_livechat_mail_channel(anonymous_name='whatever', previous_operator_id=operator.partner_id.id, user_id=operator.id)
|
||||
channel_info = self.livechat_channel.with_user(operator)._open_livechat_discuss_channel(anonymous_name='whatever', previous_operator_id=operator.partner_id.id, user_id=operator.id)
|
||||
self.assertEqual(channel_info['operator_pid'], (operator.partner_id.id, "Michel Operator"))
|
||||
self.assertFalse(channel_info['channel']['anonymous_name'])
|
||||
self.assertEqual(channel_info['channel']['anonymous_country'], [('clear',)])
|
||||
self.assertEqual(channel_info['channel']['channelMembers'], [('insert', [
|
||||
{
|
||||
'channel': {'id': channel_info['id']},
|
||||
'id': self.env['mail.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', '=', operator.partner_id.id)]).id,
|
||||
'id': self.env['discuss.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', '=', operator.partner_id.id)]).id,
|
||||
'persona': {
|
||||
'partner': {
|
||||
'active': True,
|
||||
@@ -104,24 +104,24 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
},
|
||||
])])
|
||||
|
||||
def _open_livechat_mail_channel(self):
|
||||
mail_channels = []
|
||||
def _open_livechat_discuss_channel(self):
|
||||
discuss_channels = []
|
||||
|
||||
for i in range(5):
|
||||
mail_channel = self.livechat_channel._open_livechat_mail_channel('Anonymous')
|
||||
mail_channels.append(mail_channel)
|
||||
discuss_channel = self.livechat_channel._open_livechat_discuss_channel('Anonymous')
|
||||
discuss_channels.append(discuss_channel)
|
||||
# send a message to mark this channel as 'active'
|
||||
self.env['mail.channel'].browse(mail_channel['id']).message_post(body='cc')
|
||||
self.env['discuss.channel'].browse(discuss_channel['id']).message_post(body='cc')
|
||||
|
||||
return mail_channels
|
||||
return discuss_channels
|
||||
|
||||
def test_channel_not_pinned_for_operator_before_first_message(self):
|
||||
public_user = self.env.ref('base.public_user')
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_mail_channel(anonymous_name='whatever')
|
||||
operator_channel_member = self.env['mail.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', 'in', self.operators.partner_id.ids)])
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_discuss_channel(anonymous_name='whatever')
|
||||
operator_channel_member = self.env['discuss.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', 'in', self.operators.partner_id.ids)])
|
||||
self.assertEqual(len(operator_channel_member), 1, "operator should be member of channel")
|
||||
self.assertFalse(operator_channel_member.is_pinned, "channel should not be pinned for operator initially")
|
||||
self.env['mail.channel'].browse(channel_info['id']).message_post(body='cc')
|
||||
self.env['discuss.channel'].browse(channel_info['id']).message_post(body='cc')
|
||||
self.assertTrue(operator_channel_member.is_pinned, "channel should be pinned for operator after visitor sent a message")
|
||||
self.assertIn(channel_info['id'], operator_channel_member.partner_id._get_channels_as_member().ids, "channel should be fetched by operator on new page")
|
||||
|
||||
@@ -134,8 +134,8 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
'email': 'michel@example.com',
|
||||
'livechat_username': 'Michel at your service',
|
||||
})
|
||||
channel_info = self.livechat_channel.with_user(public_user).sudo()._open_livechat_mail_channel(anonymous_name='whatever')
|
||||
channel = self.env['mail.channel'].browse(channel_info['id'])
|
||||
channel_info = self.livechat_channel.with_user(public_user).sudo()._open_livechat_discuss_channel(anonymous_name='whatever')
|
||||
channel = self.env['discuss.channel'].browse(channel_info['id'])
|
||||
channel.with_user(operator).message_post(body='Hello', message_type='comment', subtype_xmlid='mail.mt_comment')
|
||||
message_formats = channel.with_user(public_user).sudo()._channel_fetch_message()
|
||||
self.assertEqual(len(message_formats), 1)
|
||||
@@ -145,9 +145,9 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
|
||||
def test_read_channel_unpined_for_operator_after_one_day(self):
|
||||
public_user = self.env.ref('base.public_user')
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_mail_channel(anonymous_name='visitor')
|
||||
member_of_operator = self.env['mail.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', 'in', self.operators.partner_id.ids)])
|
||||
message = self.env['mail.channel'].browse(channel_info['id']).message_post(body='cc')
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_discuss_channel(anonymous_name='visitor')
|
||||
member_of_operator = self.env['discuss.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', 'in', self.operators.partner_id.ids)])
|
||||
message = self.env['discuss.channel'].browse(channel_info['id']).message_post(body='cc')
|
||||
member_of_operator.channel_id.with_user(self.operators.filtered(
|
||||
lambda operator: operator.partner_id == member_of_operator.partner_id
|
||||
))._channel_seen(message.id)
|
||||
@@ -157,9 +157,9 @@ class TestGetMailChannel(TestImLivechatCommon):
|
||||
|
||||
def test_unread_channel_not_unpined_for_operator_after_autovacuum(self):
|
||||
public_user = self.env.ref('base.public_user')
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_mail_channel(anonymous_name='visitor')
|
||||
member_of_operator = self.env['mail.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', 'in', self.operators.partner_id.ids)])
|
||||
self.env['mail.channel'].browse(channel_info['id']).message_post(body='cc')
|
||||
channel_info = self.livechat_channel.with_user(public_user)._open_livechat_discuss_channel(anonymous_name='visitor')
|
||||
member_of_operator = self.env['discuss.channel.member'].search([('channel_id', '=', channel_info['id']), ('partner_id', 'in', self.operators.partner_id.ids)])
|
||||
self.env['discuss.channel'].browse(channel_info['id']).message_post(body='cc')
|
||||
with freeze_time(fields.Datetime.to_string(fields.datetime.now() + timedelta(days=1))):
|
||||
member_of_operator._gc_unpin_livechat_sessions()
|
||||
self.assertTrue(member_of_operator.is_pinned, "unread channel should not be unpinned after autovacuum")
|
||||
@@ -10,12 +10,12 @@ class TestImLivechatReport(TestImLivechatCommon):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.env['mail.channel'].search([('livechat_channel_id', '!=', False)]).unlink()
|
||||
cls.env['discuss.channel'].search([('livechat_channel_id', '!=', False)]).unlink()
|
||||
|
||||
with patch.object(type(cls.env['im_livechat.channel']), '_get_available_users', lambda _: cls.operators):
|
||||
channel_id = cls.livechat_channel._open_livechat_mail_channel('Anonymous')['id']
|
||||
channel_id = cls.livechat_channel._open_livechat_discuss_channel('Anonymous')['id']
|
||||
|
||||
channel = cls.env['mail.channel'].browse(channel_id)
|
||||
channel = cls.env['discuss.channel'].browse(channel_id)
|
||||
cls.operator = channel.livechat_operator_id
|
||||
|
||||
cls._create_message(channel, cls.visitor_user.partner_id, '2023-03-17 06:05:54')
|
||||
|
||||
@@ -28,9 +28,9 @@ class TestImLivechatMessage(TransactionCase):
|
||||
def test_message_format(self):
|
||||
im_livechat_channel = self.env['im_livechat.channel'].sudo().create({'name': 'support', 'user_ids': [Command.link(self.users[0].id)]})
|
||||
self.users[0].im_status = 'online' # make available for livechat (ignore leave)
|
||||
channel_livechat_1 = self.env['mail.channel'].browse(im_livechat_channel._open_livechat_mail_channel(anonymous_name='anon 1', previous_operator_id=self.users[0].partner_id.id, user_id=self.users[1].id, country_id=self.env.ref('base.in').id)['id'])
|
||||
channel_livechat_1 = self.env['discuss.channel'].browse(im_livechat_channel._open_livechat_discuss_channel(anonymous_name='anon 1', previous_operator_id=self.users[0].partner_id.id, user_id=self.users[1].id, country_id=self.env.ref('base.in').id)['id'])
|
||||
record_rating = self.env['rating.rating'].create({
|
||||
'res_model_id': self.env['ir.model']._get('mail.channel').id,
|
||||
'res_model_id': self.env['ir.model']._get('discuss.channel').id,
|
||||
'res_id': channel_livechat_1.id,
|
||||
'parent_res_model_id': self.env['ir.model']._get('im_livechat.channel').id,
|
||||
'parent_res_id': im_livechat_channel.id,
|
||||
@@ -62,7 +62,7 @@ class TestImLivechatMessage(TransactionCase):
|
||||
'linkPreviews': [],
|
||||
'message_type': 'notification',
|
||||
'messageReactionGroups': [],
|
||||
'model': 'mail.channel',
|
||||
'model': 'discuss.channel',
|
||||
'module_icon': '/mail/static/description/icon.png',
|
||||
'needaction_partner_ids': [],
|
||||
'notifications': [],
|
||||
|
||||
+27
-27
@@ -2,9 +2,9 @@
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="mail_channel_view_search" model="ir.ui.view">
|
||||
<field name="name">mail.channel.search</field>
|
||||
<field name="model">mail.channel</field>
|
||||
<record id="discuss_channel_view_search" model="ir.ui.view">
|
||||
<field name="name">discuss.channel.search</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search history">
|
||||
<field name="name"/>
|
||||
@@ -17,9 +17,9 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_channel_view_tree" model="ir.ui.view">
|
||||
<field name="name">mail.channel.tree</field>
|
||||
<field name="model">mail.channel</field>
|
||||
<record id="discuss_channel_view_tree" model="ir.ui.view">
|
||||
<field name="name">discuss.channel.tree</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="History" create="false" default_order="create_date desc">
|
||||
<field name="create_date" string="Session Date"/>
|
||||
@@ -30,9 +30,9 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mail_channel_view_form" model="ir.ui.view">
|
||||
<field name="name">mail.channel.form</field>
|
||||
<field name="model">mail.channel</field>
|
||||
<record id="discuss_channel_view_form" model="ir.ui.view">
|
||||
<field name="name">discuss.channel.form</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Session Form" create="false" edit="false">
|
||||
<sheet>
|
||||
@@ -95,11 +95,11 @@
|
||||
</record>
|
||||
|
||||
|
||||
<record id="mail_channel_action" model="ir.actions.act_window">
|
||||
<record id="discuss_channel_action" model="ir.actions.act_window">
|
||||
<field name="name">History</field>
|
||||
<field name="res_model">mail.channel</field>
|
||||
<field name="res_model">discuss.channel</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="im_livechat.mail_channel_view_search"/>
|
||||
<field name="search_view_id" ref="im_livechat.discuss_channel_view_search"/>
|
||||
<field name="domain">[('livechat_channel_id', '!=', None)]</field>
|
||||
<field name="context">{'search_default_session_not_empty': 1}</field>
|
||||
<field name="help" type="html">
|
||||
@@ -110,44 +110,44 @@
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record id="mail_channel_action_tree" model="ir.actions.act_window.view">
|
||||
<record id="discuss_channel_action_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence">1</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="im_livechat.mail_channel_view_tree"/>
|
||||
<field name="act_window_id" ref="im_livechat.mail_channel_action"/>
|
||||
<field name="view_id" ref="im_livechat.discuss_channel_view_tree"/>
|
||||
<field name="act_window_id" ref="im_livechat.discuss_channel_action"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_channel_action_form" model="ir.actions.act_window.view">
|
||||
<record id="discuss_channel_action_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence">2</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="im_livechat.mail_channel_view_form"/>
|
||||
<field name="act_window_id" ref="im_livechat.mail_channel_action"/>
|
||||
<field name="view_id" ref="im_livechat.discuss_channel_view_form"/>
|
||||
<field name="act_window_id" ref="im_livechat.discuss_channel_action"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="mail_channel_action_from_livechat_channel" model="ir.actions.act_window">
|
||||
<record id="discuss_channel_action_from_livechat_channel" model="ir.actions.act_window">
|
||||
<field name="name">Sessions</field>
|
||||
<field name="res_model">mail.channel</field>
|
||||
<field name="res_model">discuss.channel</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('livechat_channel_id', 'in', [active_id]), ('has_message', '=', True)]</field>
|
||||
<field name="context">{
|
||||
'search_default_livechat_channel_id': [active_id],
|
||||
'default_livechat_channel_id': active_id,
|
||||
}</field>
|
||||
<field name="search_view_id" ref="mail_channel_view_search"/>
|
||||
<field name="search_view_id" ref="discuss_channel_view_search"/>
|
||||
</record>
|
||||
<record id="mail_channel_action_livechat_tree" model="ir.actions.act_window.view">
|
||||
<record id="discuss_channel_action_livechat_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence">1</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="im_livechat.mail_channel_view_tree"/>
|
||||
<field name="act_window_id" ref="im_livechat.mail_channel_action_from_livechat_channel"/>
|
||||
<field name="view_id" ref="im_livechat.discuss_channel_view_tree"/>
|
||||
<field name="act_window_id" ref="im_livechat.discuss_channel_action_from_livechat_channel"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_channel_action_livechat_form" model="ir.actions.act_window.view">
|
||||
<record id="discuss_channel_action_livechat_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence">2</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="im_livechat.mail_channel_view_form"/>
|
||||
<field name="act_window_id" ref="im_livechat.mail_channel_action_from_livechat_channel"/>
|
||||
<field name="view_id" ref="im_livechat.discuss_channel_view_form"/>
|
||||
<field name="act_window_id" ref="im_livechat.discuss_channel_action_from_livechat_channel"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
attrs="{'invisible': [('chatbot_script_count', '=', 0)]}">
|
||||
<field string="Chatbots" name="chatbot_script_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button class="oe_stat_button" type="action" attrs="{'invisible':[('nbr_channel','=', 0)]}" name="%(mail_channel_action_from_livechat_channel)d" icon="fa-comments">
|
||||
<button class="oe_stat_button" type="action" attrs="{'invisible':[('nbr_channel','=', 0)]}" name="%(discuss_channel_action_from_livechat_channel)d" icon="fa-comments">
|
||||
<field string="Sessions" name="nbr_channel" widget="statinfo"/>
|
||||
</button>
|
||||
<button name="action_view_rating" attrs="{'invisible':[('rating_count', '=', 0)]}" class="oe_stat_button" type="object" icon="fa-smile-o">
|
||||
@@ -299,7 +299,7 @@
|
||||
id="session_history"
|
||||
name="Sessions History"
|
||||
parent="menu_reporting_livechat"
|
||||
action="mail_channel_action"
|
||||
action="discuss_channel_action"
|
||||
groups="im_livechat_group_user"
|
||||
sequence="5"/>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
{
|
||||
'name': 'Discuss',
|
||||
'version': '1.12',
|
||||
'version': '1.13',
|
||||
'category': 'Productivity/Discuss',
|
||||
'sequence': 145,
|
||||
'summary': 'Chat, mail gateway and private channels',
|
||||
@@ -78,10 +78,10 @@ For more specific needs, you may also assign custom-defined actions
|
||||
'views/mail_mail_views.xml',
|
||||
'views/mail_followers_views.xml',
|
||||
'views/mail_ice_server_views.xml',
|
||||
'views/mail_channel_member_views.xml',
|
||||
'views/mail_channel_rtc_session_views.xml',
|
||||
'views/discuss_channel_member_views.xml',
|
||||
'views/discuss_channel_rtc_session_views.xml',
|
||||
'views/mail_link_preview_views.xml',
|
||||
'views/mail_channel_views.xml',
|
||||
'views/discuss_channel_views.xml',
|
||||
'views/mail_shortcode_views.xml',
|
||||
'views/mail_activity_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
@@ -90,7 +90,7 @@ For more specific needs, you may also assign custom-defined actions
|
||||
'data/mail_templates_chatter.xml',
|
||||
'data/mail_templates_email_layouts.xml',
|
||||
'data/mail_templates_mailgateway.xml',
|
||||
'data/mail_channel_data.xml',
|
||||
'data/discuss_channel_data.xml',
|
||||
'data/mail_activity_data.xml',
|
||||
'data/security_notifications_templates.xml',
|
||||
'data/ir_cron_data.xml',
|
||||
@@ -111,7 +111,7 @@ For more specific needs, you may also assign custom-defined actions
|
||||
'views/mail_menus.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/mail_channel_demo.xml',
|
||||
'data/discuss_channel_demo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
@@ -137,7 +137,7 @@ For more specific needs, you may also assign custom-defined actions
|
||||
'mail.assets_discuss_public_test_tours': [
|
||||
'web/static/tests/legacy/helpers/test_utils_file.js',
|
||||
'mail/static/tests/tours/discuss_public_tour.js',
|
||||
'mail/static/tests/tours/mail_channel_as_guest_tour.js',
|
||||
'mail/static/tests/tours/discuss_channel_as_guest_tour.js',
|
||||
],
|
||||
'web.assets_tests': [
|
||||
'mail/static/tests/tours/**/*',
|
||||
|
||||
@@ -20,8 +20,8 @@ class MailChatController(BusController):
|
||||
# --------------------------
|
||||
@route('/mail/chat_post', type="json", auth="public", cors="*")
|
||||
def mail_chat_post(self, uuid, message_content, **kwargs):
|
||||
mail_channel = request.env["mail.channel"].sudo().search([('uuid', '=', uuid)], limit=1)
|
||||
if not mail_channel:
|
||||
channel = request.env["discuss.channel"].sudo().search([('uuid', '=', uuid)], limit=1)
|
||||
if not channel:
|
||||
return False
|
||||
|
||||
# find the author from the user session
|
||||
@@ -31,10 +31,10 @@ class MailChatController(BusController):
|
||||
email_from = author.email_formatted
|
||||
else: # If Public User, use catchall email from company
|
||||
author_id = False
|
||||
email_from = mail_channel.anonymous_name or mail_channel.create_uid.company_id.catchall_formatted
|
||||
email_from = channel.anonymous_name or channel.create_uid.company_id.catchall_formatted
|
||||
# post a message without adding followers to the channel. email_from=False avoid to get author from email data
|
||||
body = tools.plaintext2html(message_content)
|
||||
message = mail_channel.with_context(mail_create_nosubscribe=True).message_post(
|
||||
message = channel.with_context(mail_create_nosubscribe=True).message_post(
|
||||
author_id=author_id,
|
||||
email_from=email_from,
|
||||
body=body,
|
||||
@@ -45,7 +45,7 @@ class MailChatController(BusController):
|
||||
|
||||
@route(['/mail/chat_history'], type="json", auth="public", cors="*")
|
||||
def mail_chat_history(self, uuid, last_id=False, limit=20):
|
||||
channel = request.env["mail.channel"].sudo().search([('uuid', '=', uuid)], limit=1)
|
||||
channel = request.env["discuss.channel"].sudo().search([('uuid', '=', uuid)], limit=1)
|
||||
if not channel:
|
||||
return []
|
||||
else:
|
||||
|
||||
@@ -38,20 +38,20 @@ class DiscussController(http.Controller):
|
||||
|
||||
@http.route('/chat/<int:channel_id>/<string:invitation_token>', methods=['GET'], type='http', auth='public')
|
||||
def discuss_channel_invitation(self, channel_id, invitation_token, **kwargs):
|
||||
channel_sudo = request.env['mail.channel'].browse(channel_id).sudo().exists()
|
||||
channel_sudo = request.env['discuss.channel'].browse(channel_id).sudo().exists()
|
||||
if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, invitation_token):
|
||||
raise NotFound()
|
||||
return self._response_discuss_channel_invitation(channel_sudo=channel_sudo)
|
||||
|
||||
@http.route('/discuss/channel/<int:channel_id>', methods=['GET'], type='http', auth='public')
|
||||
def discuss_channel(self, channel_id, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return self._response_discuss_public_template(channel_sudo=channel_member_sudo.channel_id)
|
||||
|
||||
def _response_discuss_channel_from_token(self, create_token, channel_name=None, default_display_mode=False):
|
||||
if not request.env['ir.config_parameter'].sudo().get_param('mail.chat_from_token'):
|
||||
raise NotFound()
|
||||
channel_sudo = request.env['mail.channel'].sudo().search([('uuid', '=', create_token)])
|
||||
channel_sudo = request.env['discuss.channel'].sudo().search([('uuid', '=', create_token)])
|
||||
if not channel_sudo:
|
||||
try:
|
||||
channel_sudo = channel_sudo.create({
|
||||
@@ -77,7 +77,7 @@ class DiscussController(http.Controller):
|
||||
'isChannelTokenSecret': is_channel_token_secret,
|
||||
}
|
||||
add_guest_cookie = False
|
||||
channel_member_sudo = channel_sudo.env['mail.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_sudo.id)
|
||||
channel_member_sudo = channel_sudo.env['discuss.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_sudo.id)
|
||||
if channel_member_sudo:
|
||||
channel_sudo = channel_member_sudo.channel_id # ensure guest is in context
|
||||
else:
|
||||
@@ -123,7 +123,7 @@ class DiscussController(http.Controller):
|
||||
'data': {
|
||||
'channelData': channel_sudo.channel_info()[0],
|
||||
'discussPublicViewData': dict({
|
||||
'channel': [('insert', {'id': channel_sudo.id, 'model': 'mail.channel'})],
|
||||
'channel': [('insert', {'id': channel_sudo.id, 'model': 'discuss.channel'})],
|
||||
'shouldDisplayWelcomeViewInitially': channel_sudo.default_display_mode == 'video_full_screen',
|
||||
}, **discuss_public_view_data),
|
||||
},
|
||||
@@ -134,50 +134,50 @@ class DiscussController(http.Controller):
|
||||
# Semi-Static Content (GET requests with possible cache)
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
@http.route('/mail/channel/<int:channel_id>/partner/<int:partner_id>/avatar_128', methods=['GET'], type='http', auth='public')
|
||||
def mail_channel_partner_avatar_128(self, channel_id, partner_id, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_id)
|
||||
@http.route('/discuss/channel/<int:channel_id>/partner/<int:partner_id>/avatar_128', methods=['GET'], type='http', auth='public')
|
||||
def discuss_channel_partner_avatar_128(self, channel_id, partner_id, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_id)
|
||||
partner_sudo = channel_member_sudo.env['res.partner'].browse(partner_id).exists()
|
||||
placeholder = partner_sudo._avatar_get_placeholder_path()
|
||||
if channel_member_sudo and channel_member_sudo.env['mail.channel.member'].search([('channel_id', '=', channel_id), ('partner_id', '=', partner_id)], limit=1):
|
||||
if channel_member_sudo and channel_member_sudo.env['discuss.channel.member'].search([('channel_id', '=', channel_id), ('partner_id', '=', partner_id)], limit=1):
|
||||
return request.env['ir.binary']._get_image_stream_from(partner_sudo, field_name='avatar_128', placeholder=placeholder).get_response()
|
||||
if request.env.user.share:
|
||||
return request.env['ir.binary']._get_placeholder_stream(placeholder).get_response()
|
||||
return request.env['ir.binary']._get_image_stream_from(partner_sudo.sudo(False), field_name='avatar_128', placeholder=placeholder).get_response()
|
||||
|
||||
@http.route('/mail/channel/<int:channel_id>/guest/<int:guest_id>/avatar_128', methods=['GET'], type='http', auth='public')
|
||||
def mail_channel_guest_avatar_128(self, channel_id, guest_id, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_id)
|
||||
@http.route('/discuss/channel/<int:channel_id>/guest/<int:guest_id>/avatar_128', methods=['GET'], type='http', auth='public')
|
||||
def discuss_channel_guest_avatar_128(self, channel_id, guest_id, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_id)
|
||||
guest_sudo = channel_member_sudo.env['mail.guest'].browse(guest_id).exists()
|
||||
placeholder = guest_sudo._avatar_get_placeholder_path()
|
||||
if channel_member_sudo and channel_member_sudo.env['mail.channel.member'].search([('channel_id', '=', channel_id), ('guest_id', '=', guest_id)], limit=1):
|
||||
if channel_member_sudo and channel_member_sudo.env['discuss.channel.member'].search([('channel_id', '=', channel_id), ('guest_id', '=', guest_id)], limit=1):
|
||||
return request.env['ir.binary']._get_image_stream_from(guest_sudo, field_name='avatar_128', placeholder=placeholder).get_response()
|
||||
if request.env.user.share:
|
||||
return request.env['ir.binary']._get_placeholder_stream(placeholder).get_response()
|
||||
return request.env['ir.binary']._get_image_stream_from(guest_sudo.sudo(False), field_name='avatar_128', placeholder=placeholder).get_response()
|
||||
|
||||
@http.route('/mail/channel/<int:channel_id>/attachment/<int:attachment_id>', methods=['GET'], type='http', auth='public')
|
||||
def mail_channel_attachment(self, channel_id, attachment_id, download=None, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
@http.route('/discuss/channel/<int:channel_id>/attachment/<int:attachment_id>', methods=['GET'], type='http', auth='public')
|
||||
def discuss_channel_attachment(self, channel_id, attachment_id, download=None, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
attachment_sudo = channel_member_sudo.env['ir.attachment'].search([
|
||||
('id', '=', int(attachment_id)),
|
||||
('res_id', '=', int(channel_id)),
|
||||
('res_model', '=', 'mail.channel')
|
||||
('res_model', '=', 'discuss.channel')
|
||||
], limit=1)
|
||||
if not attachment_sudo:
|
||||
raise NotFound()
|
||||
return request.env['ir.binary']._get_stream_from(attachment_sudo).get_response(as_attachment=download)
|
||||
|
||||
@http.route([
|
||||
'/mail/channel/<int:channel_id>/image/<int:attachment_id>',
|
||||
'/mail/channel/<int:channel_id>/image/<int:attachment_id>/<int:width>x<int:height>',
|
||||
'/discuss/channel/<int:channel_id>/image/<int:attachment_id>',
|
||||
'/discuss/channel/<int:channel_id>/image/<int:attachment_id>/<int:width>x<int:height>',
|
||||
], methods=['GET'], type='http', auth='public')
|
||||
def fetch_image(self, channel_id, attachment_id, width=0, height=0, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
attachment_sudo = channel_member_sudo.env['ir.attachment'].search([
|
||||
('id', '=', int(attachment_id)),
|
||||
('res_id', '=', int(channel_id)),
|
||||
('res_model', '=', 'mail.channel'),
|
||||
('res_model', '=', 'discuss.channel'),
|
||||
], limit=1)
|
||||
|
||||
if not attachment_sudo:
|
||||
@@ -200,9 +200,9 @@ class DiscussController(http.Controller):
|
||||
return guest.sudo()._init_messaging()
|
||||
raise NotFound()
|
||||
|
||||
@http.route('/mail/channel/members', methods=['POST'], type='json', auth='public')
|
||||
def mail_channel_members(self, channel_id, known_member_ids):
|
||||
channel_member = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=channel_id)
|
||||
@http.route('/discuss/channel/members', methods=['POST'], type='json', auth='public')
|
||||
def discuss_channel_members(self, channel_id, known_member_ids):
|
||||
channel_member = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=channel_id)
|
||||
return channel_member.channel_id.sudo().load_more_members(known_member_ids)
|
||||
|
||||
@http.route('/mail/load_message_failures', methods=['POST'], type='json', auth='user')
|
||||
@@ -234,8 +234,8 @@ class DiscussController(http.Controller):
|
||||
|
||||
@http.route('/mail/message/post', methods=['POST'], type='json', auth='public')
|
||||
def mail_message_post(self, thread_model, thread_id, post_data, **kwargs):
|
||||
if thread_model == 'mail.channel':
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(thread_id))
|
||||
if thread_model == 'discuss.channel':
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(thread_id))
|
||||
thread = channel_member_sudo.channel_id
|
||||
else:
|
||||
thread = request.env[thread_model].browse(int(thread_id)).exists()
|
||||
@@ -267,9 +267,9 @@ class DiscussController(http.Controller):
|
||||
|
||||
@http.route('/mail/attachment/upload', methods=['POST'], type='http', auth='public')
|
||||
def mail_attachment_upload(self, ufile, thread_id, thread_model, is_pending=False, **kwargs):
|
||||
channel_member = request.env['mail.channel.member']
|
||||
if thread_model == 'mail.channel':
|
||||
channel_member = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(thread_id))
|
||||
channel_member = request.env['discuss.channel.member']
|
||||
if thread_model == 'discuss.channel':
|
||||
channel_member = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(thread_id))
|
||||
vals = {
|
||||
'name': ufile.filename,
|
||||
'raw': ufile.read(),
|
||||
@@ -335,7 +335,7 @@ class DiscussController(http.Controller):
|
||||
if not message_sudo:
|
||||
raise NotFound()
|
||||
if request.env.user.sudo()._is_public():
|
||||
if not guest_sudo or not message_sudo.model == 'mail.channel' or message_sudo.res_id not in guest_sudo.channel_ids.ids:
|
||||
if not guest_sudo or not message_sudo.model == 'discuss.channel' or message_sudo.res_id not in guest_sudo.channel_ids.ids:
|
||||
raise NotFound()
|
||||
message_sudo._message_add_reaction(content=content)
|
||||
guests = [('insert', {'id': guest_sudo.id})]
|
||||
@@ -363,7 +363,7 @@ class DiscussController(http.Controller):
|
||||
if not message_sudo:
|
||||
raise NotFound()
|
||||
if request.env.user.sudo()._is_public():
|
||||
if not guest_sudo or not message_sudo.model == 'mail.channel' or message_sudo.res_id not in guest_sudo.channel_ids.ids:
|
||||
if not guest_sudo or not message_sudo.model == 'discuss.channel' or message_sudo.res_id not in guest_sudo.channel_ids.ids:
|
||||
raise NotFound()
|
||||
message_sudo._message_remove_reaction(content=content)
|
||||
guests = [('insert-and-unlink', {'id': guest_sudo.id})]
|
||||
@@ -388,9 +388,9 @@ class DiscussController(http.Controller):
|
||||
# Channel API
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
@http.route('/mail/channel/add_guest_as_member', methods=['POST'], type='json', auth='public')
|
||||
def mail_channel_add_guest_as_member(self, channel_id, channel_uuid, **kwargs):
|
||||
channel_sudo = request.env['mail.channel'].browse(int(channel_id)).sudo().exists()
|
||||
@http.route('/discuss/channel/add_guest_as_member', methods=['POST'], type='json', auth='public')
|
||||
def discuss_channel_add_guest_as_member(self, channel_id, channel_uuid, **kwargs):
|
||||
channel_sudo = request.env['discuss.channel'].browse(int(channel_id)).sudo().exists()
|
||||
if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, channel_uuid):
|
||||
raise NotFound()
|
||||
if channel_sudo.channel_type == 'chat':
|
||||
@@ -399,7 +399,7 @@ class DiscussController(http.Controller):
|
||||
# Only guests should take this route.
|
||||
if not guest:
|
||||
raise NotFound()
|
||||
channel_member = channel_sudo.env['mail.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_id)
|
||||
channel_member = channel_sudo.env['discuss.channel.member']._get_as_sudo_from_request(request=request, channel_id=channel_id)
|
||||
# Do not add the guest to channel members if they are already member.
|
||||
if not channel_member:
|
||||
channel_sudo = channel_sudo.with_context(guest=guest)
|
||||
@@ -408,12 +408,12 @@ class DiscussController(http.Controller):
|
||||
except UserError:
|
||||
raise NotFound()
|
||||
|
||||
@http.route('/mail/channel/messages', methods=['POST'], type='json', auth='public')
|
||||
def mail_channel_messages(self, channel_id, before=None, after=None, limit=30, around=None, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
@http.route('/discuss/channel/messages', methods=['POST'], type='json', auth='public')
|
||||
def discuss_channel_messages(self, channel_id, before=None, after=None, limit=30, around=None, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
domain = [
|
||||
('res_id', '=', channel_id),
|
||||
('model', '=', 'mail.channel'),
|
||||
('model', '=', 'discuss.channel'),
|
||||
('message_type', '!=', 'user_notification'),
|
||||
]
|
||||
messages = channel_member_sudo.env['mail.message']._message_fetch(domain=domain, before=before, after=after, around=around, limit=limit)
|
||||
@@ -421,24 +421,24 @@ class DiscussController(http.Controller):
|
||||
messages.set_message_done()
|
||||
return messages.sorted('id', reverse=True).message_format()
|
||||
|
||||
@http.route('/mail/channel/pinned_messages', methods=['POST'], type='json', auth='public')
|
||||
def mail_channel_pins(self, channel_id, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
@http.route('/discuss/channel/pinned_messages', methods=['POST'], type='json', auth='public')
|
||||
def discuss_channel_pins(self, channel_id, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return channel_member_sudo.channel_id.pinned_message_ids.sorted(key='pinned_at', reverse=True).message_format()
|
||||
|
||||
@http.route('/mail/channel/set_last_seen_message', methods=['POST'], type='json', auth='public')
|
||||
def mail_channel_mark_as_seen(self, channel_id, last_message_id, allow_older=False, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
@http.route('/discuss/channel/set_last_seen_message', methods=['POST'], type='json', auth='public')
|
||||
def discuss_channel_mark_as_seen(self, channel_id, last_message_id, allow_older=False, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return channel_member_sudo.channel_id._channel_seen(last_message_id, allow_older=allow_older)
|
||||
|
||||
@http.route('/mail/channel/notify_typing', methods=['POST'], type='json', auth='public')
|
||||
def mail_channel_notify_typing(self, channel_id, is_typing, **kwargs):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
@http.route('/discuss/channel/notify_typing', methods=['POST'], type='json', auth='public')
|
||||
def discuss_channel_notify_typing(self, channel_id, is_typing, **kwargs):
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo._notify_typing(is_typing)
|
||||
|
||||
@http.route('/mail/channel/ping', methods=['POST'], type='json', auth='public')
|
||||
@http.route('/discuss/channel/ping', methods=['POST'], type='json', auth='public')
|
||||
def channel_ping(self, channel_id, rtc_session_id=None, check_rtc_session_ids=None):
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
if rtc_session_id:
|
||||
channel_member_sudo.channel_id.rtc_session_ids.filtered_domain([
|
||||
('id', '=', int(rtc_session_id)),
|
||||
@@ -516,7 +516,7 @@ class DiscussController(http.Controller):
|
||||
guest = request.env['mail.guest']._get_guest_from_request(request)
|
||||
notifications_by_session = defaultdict(list)
|
||||
for sender_session_id, target_session_ids, content in peer_notifications:
|
||||
session_sudo = guest.env['mail.channel.rtc.session'].sudo().browse(int(sender_session_id)).exists()
|
||||
session_sudo = guest.env['discuss.channel.rtc.session'].sudo().browse(int(sender_session_id)).exists()
|
||||
if not session_sudo or (session_sudo.guest_id and session_sudo.guest_id != guest) or (session_sudo.partner_id and session_sudo.partner_id != request.env.user.partner_id):
|
||||
continue
|
||||
notifications_by_session[session_sudo].append(([int(sid) for sid in target_session_ids], content))
|
||||
@@ -533,12 +533,12 @@ class DiscussController(http.Controller):
|
||||
if request.env.user._is_public():
|
||||
guest = request.env['mail.guest']._get_guest_from_request(request)
|
||||
if guest:
|
||||
session = guest.env['mail.channel.rtc.session'].sudo().browse(int(session_id)).exists()
|
||||
session = guest.env['discuss.channel.rtc.session'].sudo().browse(int(session_id)).exists()
|
||||
if session and session.guest_id == guest:
|
||||
session._update_and_broadcast(values)
|
||||
return
|
||||
return
|
||||
session = request.env['mail.channel.rtc.session'].sudo().browse(int(session_id)).exists()
|
||||
session = request.env['discuss.channel.rtc.session'].sudo().browse(int(session_id)).exists()
|
||||
if session and session.partner_id == request.env.user.partner_id:
|
||||
session._update_and_broadcast(values)
|
||||
|
||||
@@ -547,7 +547,7 @@ class DiscussController(http.Controller):
|
||||
""" Joins the RTC call of a channel if the user is a member of that channel
|
||||
:param int channel_id: id of the channel to join
|
||||
"""
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return channel_member_sudo._rtc_join_call(check_rtc_session_ids=check_rtc_session_ids)
|
||||
|
||||
@http.route('/mail/rtc/channel/leave_call', methods=['POST'], type="json", auth="public")
|
||||
@@ -555,7 +555,7 @@ class DiscussController(http.Controller):
|
||||
""" Disconnects the current user from a rtc call and clears any invitation sent to that user on this channel
|
||||
:param int channel_id: id of the channel from which to disconnect
|
||||
"""
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return channel_member_sudo._rtc_leave_call()
|
||||
|
||||
@http.route('/mail/rtc/channel/cancel_call_invitation', methods=['POST'], type="json", auth="public")
|
||||
@@ -564,7 +564,7 @@ class DiscussController(http.Controller):
|
||||
:param member_ids: members whose invitation is to cancel
|
||||
:type member_ids: list(int) or None
|
||||
"""
|
||||
channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_member_sudo = request.env['discuss.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return channel_member_sudo.channel_id._rtc_cancel_invitations(member_ids=member_ids)
|
||||
|
||||
@http.route('/mail/rtc/audio_worklet_processor', methods=['GET'], type='http', auth='public')
|
||||
|
||||
@@ -8,10 +8,10 @@ from odoo.addons.web.controllers.home import Home as WebHome
|
||||
def _admin_password_warn(uid):
|
||||
""" Admin still has `admin` password, flash a message via chatter.
|
||||
|
||||
Uses a private mail.channel from the system (/ odoobot) to the user, as
|
||||
Uses a private discuss.channel from the system (/ odoobot) to the user, as
|
||||
using a more generic mail.thread could send an email which is undesirable
|
||||
|
||||
Uses mail.channel directly because using mail.thread might send an email instead.
|
||||
Uses discuss.channel directly because using mail.thread might send an email instead.
|
||||
"""
|
||||
if request.params['password'] != 'admin':
|
||||
return
|
||||
@@ -26,8 +26,8 @@ def _admin_password_warn(uid):
|
||||
return
|
||||
|
||||
user = request.env(user=uid)['res.users']
|
||||
MailChannel = env(context=user.context_get())['mail.channel']
|
||||
MailChannel.browse(MailChannel.channel_get([admin.id])['id'])\
|
||||
DiscussChannel = env(context=user.context_get())['discuss.channel']
|
||||
DiscussChannel.browse(DiscussChannel.channel_get([admin.id])['id'])\
|
||||
.message_post(
|
||||
body=_("Your password is the default (admin)! If this system is exposed to untrusted users it is important to change it immediately for security reasons. I will keep nagging you about it!"),
|
||||
message_type='comment',
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record model="mail.channel" id="channel_all_employees">
|
||||
<record model="discuss.channel" id="mail.channel_all_employees">
|
||||
<field name="name">general</field>
|
||||
<field name="description">General announcements for all employees.</field>
|
||||
</record>
|
||||
|
||||
<!-- notify all employees of module installation -->
|
||||
<record model="mail.message" id="module_install_notification">
|
||||
<field name="model">mail.channel</field>
|
||||
<record model="mail.message" id="mail.module_install_notification">
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_all_employees"/>
|
||||
<field name="message_type">email</field>
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
@@ -18,14 +18,14 @@
|
||||
<p>This channel is accessible to all users to <b>easily share company information</b>.</p>]]></field>
|
||||
</record>
|
||||
|
||||
<record model="mail.channel.member" id="channel_member_general_channel_for_admin">
|
||||
<record model="discuss.channel.member" id="channel_member_general_channel_for_admin">
|
||||
<field name="partner_id" ref="base.partner_admin"/>
|
||||
<field name="channel_id" ref="mail.channel_all_employees"/>
|
||||
<field name="fetched_message_id" ref="mail.module_install_notification"/>
|
||||
<field name="seen_message_id" ref="mail.module_install_notification"/>
|
||||
</record>
|
||||
|
||||
<record model="mail.channel" id="mail.channel_all_employees">
|
||||
<record model="discuss.channel" id="mail.channel_all_employees">
|
||||
<field name="group_ids" eval="[Command.link(ref('base.group_user'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
+15
-15
@@ -3,52 +3,52 @@
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Discussion groups, done in 2 steps to remove creator from followers -->
|
||||
<record model="mail.channel" id="channel_1">
|
||||
<record model="discuss.channel" id="mail.channel_1">
|
||||
<field name="name">sales</field>
|
||||
<field name="description">Discussion about best sales practices and deals.</field>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_2">
|
||||
<record model="discuss.channel" id="mail.channel_2">
|
||||
<field name="name">board-meetings</field>
|
||||
<field name="description">Board meetings, budgets, strategic plans</field>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_3">
|
||||
<record model="discuss.channel" id="mail.channel_3">
|
||||
<field name="name">rd</field>
|
||||
<field name="description">Research and development discussion group</field>
|
||||
</record>
|
||||
|
||||
<!-- Best sales practices messages -->
|
||||
<record id="mail_message_channel_1_1" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_1"/>
|
||||
<field name="body"><![CDATA[<p>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.</p>]]></field>
|
||||
<field name="message_type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="date" eval="(DateTime.today() - timedelta(days=5)).strftime('%Y-%m-%d %H:%M')"/>
|
||||
</record>
|
||||
<record id="mail_message_channel_1_2" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_1"/>
|
||||
<field name="body"><![CDATA[<p>I noted I can not manage efficiently my pipeline when I have more than 50 opportunities in the qualification stage.</p><p>Any advice on this? How do you organize your activities with more than 50 opportunities?</p>]]></field>
|
||||
<field name="message_type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_root"/>
|
||||
<field name="date" eval="(DateTime.today() - timedelta(days=4)).strftime('%Y-%m-%d %H:%M')"/>
|
||||
</record>
|
||||
<record id="mail_message_channel_1_2_1" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_1"/>
|
||||
<field name="body"><![CDATA[<p>When I have too much opportunities in the pipe, I start communicating with prospects more by email than phonecalls.</p><p>I send an email to create a sense of emergency, like <i>"can I call you this week about our quote?"</i> and I call only those that answer this email.</p><p>You can use the email template feature of Odoo to automate email composition.</p>]]></field>
|
||||
<field name="message_type">comment</field>
|
||||
<field name="parent_id" ref="mail_message_channel_1_2"/>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="date" eval="(DateTime.today() - timedelta(days=3)).strftime('%Y-%m-%d %H:%M')"/>
|
||||
</record>
|
||||
|
||||
<!-- Pushed to all employees -->
|
||||
<record id="mail_message_channel_whole_1" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_all_employees"/>
|
||||
<field name="body"><![CDATA[
|
||||
<p>
|
||||
@@ -64,7 +64,7 @@
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
</record>
|
||||
<record id="mail_message_channel_whole_2" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_all_employees"/>
|
||||
<field name="body"><![CDATA[<p>Your monthly meal vouchers arrived. You can get them at the HR's office.</p>
|
||||
<p>This month you also get 250 EUR of eco-vouchers if you have been in the company for more than a year.</p>]]></field>
|
||||
@@ -74,7 +74,7 @@
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
</record>
|
||||
<record id="mail_message_channel_whole_2_1" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="channel_all_employees"/>
|
||||
<field name="body"><![CDATA[<p>Thanks! Could you please remind me where is Christine's office, if I may ask? I'm new here!</p>]]></field>
|
||||
<field name="parent_id" ref="mail_message_channel_whole_2"/>
|
||||
@@ -84,7 +84,7 @@
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
</record>
|
||||
<record id="mail_message_channel_whole_2_2" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="channel_all_employees"/>
|
||||
<field name="body"><![CDATA[<p>Building B3, second floor to the right :-).</p>]]></field>
|
||||
<field name="parent_id" ref="mail_message_channel_whole_2_1"/>
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
<!-- Board messages -->
|
||||
<record id="mail_message_channel_2_1" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="model">discuss.channel</field>
|
||||
<field name="res_id" ref="mail.channel_2"/>
|
||||
<field name="body"><![CDATA[
|
||||
<p>
|
||||
@@ -150,7 +150,7 @@
|
||||
</p>
|
||||
]]></field>
|
||||
<field name="message_type">comment</field>
|
||||
<field name="subtype_id" ref="mt_comment"/>
|
||||
<field name="subtype_id" ref="mail.mt_comment"/>
|
||||
<field name="author_id" ref="base.partner_demo"/>
|
||||
<field name="date" eval="(DateTime.today() - timedelta(days=3)).strftime('%Y-%m-%d %H:%M')"/>
|
||||
</record>
|
||||
@@ -34,9 +34,9 @@ from . import mail_tracking_value
|
||||
from . import mail_template
|
||||
|
||||
# discuss
|
||||
from . import mail_channel_member
|
||||
from . import mail_channel_rtc_session
|
||||
from . import mail_channel
|
||||
from . import discuss_channel_member
|
||||
from . import discuss_channel_rtc_session
|
||||
from . import discuss_channel
|
||||
from . import mail_guest
|
||||
from . import mail_ice_server
|
||||
from . import mail_shortcode
|
||||
|
||||
@@ -29,10 +29,10 @@ group_avatar = '''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 530.06 53
|
||||
|
||||
|
||||
class Channel(models.Model):
|
||||
""" A mail.channel is a discussion group that may behave like a listener
|
||||
""" A discuss.channel is a discussion group that may behave like a listener
|
||||
on documents. """
|
||||
_description = 'Discussion Channel'
|
||||
_name = 'mail.channel'
|
||||
_name = 'discuss.channel'
|
||||
_mail_flat_thread = False
|
||||
_mail_post_access = 'read'
|
||||
_inherit = ['mail.thread']
|
||||
@@ -65,10 +65,10 @@ class Channel(models.Model):
|
||||
compute_sudo=True, search='_search_channel_partner_ids',
|
||||
groups='base.group_user')
|
||||
channel_member_ids = fields.One2many(
|
||||
'mail.channel.member', 'channel_id', string='Members',
|
||||
'discuss.channel.member', 'channel_id', string='Members',
|
||||
groups='base.group_user')
|
||||
pinned_message_ids = fields.One2many('mail.message', 'res_id', domain=lambda self: [('model', '=', 'mail.channel'), ('pinned_at', '!=', False)], string='Pinned Messages')
|
||||
rtc_session_ids = fields.One2many('mail.channel.rtc.session', 'channel_id', groups="base.group_system")
|
||||
pinned_message_ids = fields.One2many('mail.message', 'res_id', domain=lambda self: [('model', '=', 'discuss.channel'), ('pinned_at', '!=', False)], string='Pinned Messages')
|
||||
rtc_session_ids = fields.One2many('discuss.channel.rtc.session', 'channel_id', groups="base.group_system")
|
||||
is_member = fields.Boolean('Is Member', compute='_compute_is_member', search='_search_is_member')
|
||||
member_count = fields.Integer(string="Member Count", compute='_compute_member_count', compute_sudo=True)
|
||||
group_ids = fields.Many2many(
|
||||
@@ -130,7 +130,7 @@ class Channel(models.Model):
|
||||
|
||||
def _inverse_channel_partner_ids(self):
|
||||
new_members = []
|
||||
outdated = self.env['mail.channel.member']
|
||||
outdated = self.env['discuss.channel.member']
|
||||
for channel in self:
|
||||
current_members = channel.channel_member_ids
|
||||
partners = channel.channel_partner_ids
|
||||
@@ -143,7 +143,7 @@ class Channel(models.Model):
|
||||
outdated += current_members.filtered(lambda m: m.partner_id not in partners)
|
||||
|
||||
if new_members:
|
||||
self.env['mail.channel.member'].create(new_members)
|
||||
self.env['discuss.channel.member'].create(new_members)
|
||||
if outdated:
|
||||
outdated.sudo().unlink()
|
||||
|
||||
@@ -151,7 +151,7 @@ class Channel(models.Model):
|
||||
return [(
|
||||
'channel_member_ids',
|
||||
'in',
|
||||
self.env['mail.channel.member'].sudo()._search([
|
||||
self.env['discuss.channel.member'].sudo()._search([
|
||||
('partner_id', operator, operand)
|
||||
])
|
||||
)]
|
||||
@@ -169,7 +169,7 @@ class Channel(models.Model):
|
||||
user_domain = [('guest_id', '=', guest.id)]
|
||||
else:
|
||||
user_domain = [('partner_id', '=', self.env.user.partner_id.id)]
|
||||
members = self.env['mail.channel.member'].sudo().search(expression.AND([[('channel_id', 'in', self.ids)], user_domain]))
|
||||
members = self.env['discuss.channel.member'].sudo().search(expression.AND([[('channel_id', 'in', self.ids)], user_domain]))
|
||||
is_member_channels = {member.channel_id for member in members}
|
||||
for channel in self:
|
||||
channel.is_member = channel in is_member_channels
|
||||
@@ -186,12 +186,12 @@ class Channel(models.Model):
|
||||
return [(
|
||||
'channel_member_ids',
|
||||
'in' if is_in else 'not in',
|
||||
self.env['mail.channel.member'].sudo()._search(user_domain)
|
||||
self.env['discuss.channel.member'].sudo()._search(user_domain)
|
||||
)]
|
||||
|
||||
@api.depends('channel_member_ids')
|
||||
def _compute_member_count(self):
|
||||
read_group_res = self.env['mail.channel.member']._read_group(domain=[('channel_id', 'in', self.ids)], groupby=['channel_id'], aggregates=['__count'])
|
||||
read_group_res = self.env['discuss.channel.member']._read_group(domain=[('channel_id', 'in', self.ids)], groupby=['channel_id'], aggregates=['__count'])
|
||||
member_count_by_channel_id = {channel.id: count for channel, count in read_group_res}
|
||||
for channel in self:
|
||||
channel.member_count = member_count_by_channel_id.get(channel.id, 0)
|
||||
@@ -239,7 +239,7 @@ class Channel(models.Model):
|
||||
vals.pop('channel_partner_ids', False)
|
||||
|
||||
# Create channel and alias
|
||||
channels = super(Channel, self.with_context(mail_create_bypass_create_check=self.env['mail.channel.member']._bypass_create_check, mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals_list)
|
||||
channels = super(Channel, self.with_context(mail_create_bypass_create_check=self.env['discuss.channel.member']._bypass_create_check, mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals_list)
|
||||
|
||||
channels._subscribe_users_automatically()
|
||||
|
||||
@@ -247,7 +247,7 @@ class Channel(models.Model):
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_all_employee_channel(self):
|
||||
# Delete mail.channel
|
||||
# Delete discuss.channel
|
||||
try:
|
||||
all_emp_group = self.env.ref('mail.channel_all_employees')
|
||||
except ValueError:
|
||||
@@ -276,9 +276,9 @@ class Channel(models.Model):
|
||||
return result
|
||||
|
||||
def init(self):
|
||||
self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('mail_channel_member_seen_message_id_idx',))
|
||||
self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = %s', ('discuss_channel_member_seen_message_id_idx',))
|
||||
if not self._cr.fetchone():
|
||||
self._cr.execute('CREATE INDEX mail_channel_member_seen_message_id_idx ON mail_channel_member (channel_id,partner_id,seen_message_id)')
|
||||
self._cr.execute('CREATE INDEX discuss_channel_member_seen_message_id_idx ON discuss_channel_member (channel_id,partner_id,seen_message_id)')
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MEMBERS MANAGEMENT
|
||||
@@ -292,7 +292,7 @@ class Channel(models.Model):
|
||||
for channel_id in new_members
|
||||
for partner_id in new_members[channel_id]
|
||||
]
|
||||
self.env['mail.channel.member'].sudo().create(to_create)
|
||||
self.env['discuss.channel.member'].sudo().create(to_create)
|
||||
|
||||
def _subscribe_users_automatically_get_members(self):
|
||||
""" Return new members per channel ID """
|
||||
@@ -309,13 +309,13 @@ class Channel(models.Model):
|
||||
if partner not in self.with_context(active_test=False).channel_partner_ids:
|
||||
return True
|
||||
channel_info = self.channel_info()[0] # must be computed before leaving the channel (access rights)
|
||||
member = self.env['mail.channel.member'].search([('channel_id', '=', self.id), ('partner_id', '=', partner.id)])
|
||||
member = self.env['discuss.channel.member'].search([('channel_id', '=', self.id), ('partner_id', '=', partner.id)])
|
||||
member_id = member.id
|
||||
member.unlink()
|
||||
# side effect of unsubscribe that wasn't taken into account because
|
||||
# channel_info is called before actually unpinning the channel
|
||||
channel_info['is_pinned'] = False
|
||||
self.env['bus.bus']._sendone(partner, 'mail.channel/leave', channel_info)
|
||||
self.env['bus.bus']._sendone(partner, 'discuss.channel/leave', channel_info)
|
||||
notification = Markup('<div class="o_mail_notification">%s</div>') % _('left the channel')
|
||||
# post 'channel left' message as root since the partner just unsubscribed from the channel
|
||||
self.sudo().message_post(body=notification, subtype_xmlid="mail.mt_comment", author_id=partner.id)
|
||||
@@ -359,7 +359,7 @@ class Channel(models.Model):
|
||||
group_name=channel.group_public_id.name,
|
||||
guest_names=', '.join(guest.name for guest in guests)
|
||||
))
|
||||
existing_members = self.env['mail.channel.member'].search(expression.AND([
|
||||
existing_members = self.env['discuss.channel.member'].search(expression.AND([
|
||||
[('channel_id', '=', channel.id)],
|
||||
expression.OR([
|
||||
[('partner_id', 'in', partners.ids)],
|
||||
@@ -374,12 +374,12 @@ class Channel(models.Model):
|
||||
'guest_id': guest.id,
|
||||
'channel_id': channel.id,
|
||||
} for guest in guests - existing_members.guest_id]
|
||||
new_members = self.env['mail.channel.member'].sudo().create(members_to_create)
|
||||
new_members = self.env['discuss.channel.member'].sudo().create(members_to_create)
|
||||
for member in new_members.filtered(lambda member: member.partner_id):
|
||||
# notify invited members through the bus
|
||||
user = member.partner_id.user_ids[0] if member.partner_id.user_ids else self.env['res.users']
|
||||
if user:
|
||||
notifications.append((member.partner_id, 'mail.channel/joined', {
|
||||
notifications.append((member.partner_id, 'discuss.channel/joined', {
|
||||
'channel': member.channel_id.with_user(user).with_context(allowed_company_ids=user.company_ids.ids).sudo().channel_info()[0],
|
||||
'invited_by_user_id': self.env.user.id,
|
||||
'open_chat_window': open_chat_window,
|
||||
@@ -397,12 +397,12 @@ class Channel(models.Model):
|
||||
message_type="notification", subtype_xmlid="mail.mt_comment")
|
||||
guest = member.guest_id
|
||||
if guest:
|
||||
notifications.append((guest, 'mail.channel/joined', {
|
||||
notifications.append((guest, 'discuss.channel/joined', {
|
||||
'channel': member.channel_id.sudo().channel_info()[0],
|
||||
}))
|
||||
notifications.append((channel, 'mail.record/insert', {
|
||||
'Channel': {
|
||||
'channelMembers': [('insert', list(new_members._mail_channel_member_format().values()))],
|
||||
'channelMembers': [('insert', list(new_members._discuss_channel_member_format().values()))],
|
||||
'id': channel.id,
|
||||
'memberCount': channel.member_count,
|
||||
}
|
||||
@@ -413,14 +413,14 @@ class Channel(models.Model):
|
||||
# create channel from form view, and then join from discuss without refreshing the page.
|
||||
notifications.append((current_partner or current_guest, 'mail.record/insert', {
|
||||
'Channel': {
|
||||
'channelMembers': [('insert', list(existing_members._mail_channel_member_format().values()))],
|
||||
'channelMembers': [('insert', list(existing_members._discuss_channel_member_format().values()))],
|
||||
'id': channel.id,
|
||||
'memberCount': channel.member_count,
|
||||
}
|
||||
}))
|
||||
if invite_to_rtc_call:
|
||||
for channel in self:
|
||||
current_channel_member = self.env['mail.channel.member'].sudo().search([('channel_id', '=', channel.id), ('partner_id', '=', current_partner.id), ('guest_id', '=', current_guest.id)])
|
||||
current_channel_member = self.env['discuss.channel.member'].sudo().search([('channel_id', '=', channel.id), ('partner_id', '=', current_partner.id), ('guest_id', '=', current_guest.id)])
|
||||
if current_channel_member and current_channel_member.rtc_session_ids:
|
||||
current_channel_member._rtc_invite_members(member_ids=new_members.ids)
|
||||
self.env['bus.bus']._sendmany(notifications)
|
||||
@@ -463,7 +463,7 @@ class Channel(models.Model):
|
||||
if member_ids:
|
||||
channel_member_domain = expression.AND([channel_member_domain, [('id', 'in', member_ids)]])
|
||||
invitation_notifications = []
|
||||
members = self.env['mail.channel.member'].search(channel_member_domain)
|
||||
members = self.env['discuss.channel.member'].search(channel_member_domain)
|
||||
for member in members:
|
||||
member.rtc_inviting_session_id = False
|
||||
if member.partner_id:
|
||||
@@ -473,14 +473,14 @@ class Channel(models.Model):
|
||||
invitation_notifications.append((target, 'mail.record/insert', {
|
||||
'Thread': {
|
||||
'id': self.id,
|
||||
'model': 'mail.channel',
|
||||
'model': 'discuss.channel',
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
}
|
||||
}))
|
||||
self.env['bus.bus']._sendmany(invitation_notifications)
|
||||
channel_data = {'id': self.id, 'model': 'mail.channel'}
|
||||
channel_data = {'id': self.id, 'model': 'discuss.channel'}
|
||||
if members:
|
||||
channel_data['invitedMembers'] = [('insert-and-unlink', list(members._mail_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))]
|
||||
channel_data['invitedMembers'] = [('insert-and-unlink', list(members._discuss_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))]
|
||||
self.env['bus.bus']._sendone(self, 'mail.record/insert', {'Thread': channel_data})
|
||||
return channel_data
|
||||
|
||||
@@ -570,7 +570,7 @@ class Channel(models.Model):
|
||||
# notification of the message itself to ensure the channel automatically opens.
|
||||
if self.is_chat or self.channel_type == 'group':
|
||||
for member in self.channel_member_ids.filtered('partner_id'):
|
||||
bus_notifications.insert(0, [member.partner_id, 'mail.channel/last_interest_dt_changed', {
|
||||
bus_notifications.insert(0, [member.partner_id, 'discuss.channel/last_interest_dt_changed', {
|
||||
'id': self.id,
|
||||
'isServerPinned': member.is_pinned,
|
||||
'last_interest_dt': member.last_interest_dt,
|
||||
@@ -609,7 +609,7 @@ class Channel(models.Model):
|
||||
# mail_post_autofollow=False is necessary to prevent adding followers
|
||||
# when using mentions in channels. Followers should not be added to
|
||||
# channels, and especially not automatically (because channel membership
|
||||
# should be managed with mail.channel.member instead).
|
||||
# should be managed with discuss.channel.member instead).
|
||||
# The current client code might be setting the key to True on sending
|
||||
# message but it is only useful when targeting customers in chatter.
|
||||
# This value should simply be set to False in channels no matter what.
|
||||
@@ -626,7 +626,7 @@ class Channel(models.Model):
|
||||
""" We don't call super in this override as we want to ignore the
|
||||
mail.thread behavior completely """
|
||||
if not message.message_type == 'comment':
|
||||
raise UserError(_("Only messages type comment can have their content updated on model 'mail.channel'"))
|
||||
raise UserError(_("Only messages type comment can have their content updated on model 'discuss.channel'"))
|
||||
|
||||
def _message_update_content_after_hook(self, message):
|
||||
self.ensure_one()
|
||||
@@ -715,7 +715,7 @@ class Channel(models.Model):
|
||||
allowed_company_ids=user_id.company_ids.ids
|
||||
)
|
||||
for channel_info in user_channels.channel_info():
|
||||
notifications.append((partner, 'mail.channel/legacy_insert', channel_info))
|
||||
notifications.append((partner, 'discuss.channel/legacy_insert', channel_info))
|
||||
return notifications
|
||||
|
||||
def _channel_message_notifications(self, message, message_format=False):
|
||||
@@ -732,7 +732,7 @@ class Channel(models.Model):
|
||||
'id': channel.id,
|
||||
'message': message_format,
|
||||
}
|
||||
notifications.append((channel, 'mail.channel/new_message', payload))
|
||||
notifications.append((channel, 'discuss.channel/new_message', payload))
|
||||
return notifications
|
||||
|
||||
# ------------------------------------------------------------
|
||||
@@ -754,7 +754,7 @@ class Channel(models.Model):
|
||||
self.ensure_one()
|
||||
message_to_update = self.env['mail.message'].search([
|
||||
['id', '=', message_id],
|
||||
['model', '=', 'mail.channel'],
|
||||
['model', '=', 'discuss.channel'],
|
||||
['res_id', '=', self.id],
|
||||
['pinned_at', '=' if pinned else '!=', False]
|
||||
])
|
||||
@@ -808,11 +808,11 @@ class Channel(models.Model):
|
||||
[('partner_id', '=', current_partner.id) if current_partner else expression.FALSE_LEAF],
|
||||
[('guest_id', '=', current_guest.id) if current_guest else expression.FALSE_LEAF],
|
||||
])
|
||||
all_needed_members = self.env['mail.channel.member'].search(expression.AND([[('channel_id', 'in', self.ids)], all_needed_members_domain]), order='id')
|
||||
all_needed_members = self.env['discuss.channel.member'].search(expression.AND([[('channel_id', 'in', self.ids)], all_needed_members_domain]), order='id')
|
||||
all_needed_members.partner_id.sudo().mail_partner_format() # prefetch in batch
|
||||
members_by_channel = defaultdict(lambda: self.env['mail.channel.member'])
|
||||
invited_members_by_channel = defaultdict(lambda: self.env['mail.channel.member'])
|
||||
member_of_current_user_by_channel = defaultdict(lambda: self.env['mail.channel.member'])
|
||||
members_by_channel = defaultdict(lambda: self.env['discuss.channel.member'])
|
||||
invited_members_by_channel = defaultdict(lambda: self.env['discuss.channel.member'])
|
||||
member_of_current_user_by_channel = defaultdict(lambda: self.env['discuss.channel.member'])
|
||||
for member in all_needed_members:
|
||||
members_by_channel[member.channel_id] |= member
|
||||
if member.rtc_inviting_session_id:
|
||||
@@ -843,9 +843,9 @@ class Channel(models.Model):
|
||||
# find the channel member state
|
||||
if current_partner or current_guest:
|
||||
info['message_needaction_counter'] = channel.message_needaction_counter
|
||||
member = member_of_current_user_by_channel.get(channel, self.env['mail.channel.member']).with_prefetch([m.id for m in member_of_current_user_by_channel.values()])
|
||||
member = member_of_current_user_by_channel.get(channel, self.env['discuss.channel.member']).with_prefetch([m.id for m in member_of_current_user_by_channel.values()])
|
||||
if member:
|
||||
channel_data['channelMembers'] = [('insert', list(member._mail_channel_member_format().values()))]
|
||||
channel_data['channelMembers'] = [('insert', list(member._discuss_channel_member_format().values()))]
|
||||
info['state'] = member.fold_state or 'open'
|
||||
channel_data['message_unread_counter'] = member.message_unread_counter
|
||||
info['is_minimized'] = member.is_minimized
|
||||
@@ -860,7 +860,7 @@ class Channel(models.Model):
|
||||
# avoid sending potentially a lot of members for big channels
|
||||
# exclude chat and other small channels from this optimization because they are
|
||||
# assumed to be smaller and it's important to know the member list for them
|
||||
channel_data['channelMembers'] = [('insert', list(members_by_channel[channel]._mail_channel_member_format().values()))]
|
||||
channel_data['channelMembers'] = [('insert', list(members_by_channel[channel]._discuss_channel_member_format().values()))]
|
||||
info['seen_partners_info'] = sorted([{
|
||||
'id': cp.id,
|
||||
'partner_id': cp.partner_id.id,
|
||||
@@ -869,7 +869,7 @@ class Channel(models.Model):
|
||||
} for cp in members_by_channel[channel] if cp.partner_id], key=lambda p: p['partner_id'])
|
||||
# add RTC sessions info
|
||||
info.update({
|
||||
'invitedMembers': [('insert', list(invited_members_by_channel[channel]._mail_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))],
|
||||
'invitedMembers': [('insert', list(invited_members_by_channel[channel]._discuss_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))],
|
||||
'rtcSessions': [('insert', rtc_sessions_by_channel.get(channel, []))],
|
||||
})
|
||||
|
||||
@@ -886,7 +886,7 @@ class Channel(models.Model):
|
||||
:rtype : list(dict)
|
||||
"""
|
||||
self.ensure_one()
|
||||
domain = ["&", ("model", "=", "mail.channel"), ("res_id", "in", self.ids)]
|
||||
domain = ["&", ("model", "=", "discuss.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).message_format()
|
||||
@@ -919,16 +919,16 @@ class Channel(models.Model):
|
||||
raise UserError(_("A chat should not be created with more than 2 persons. Create a group instead."))
|
||||
# determine type according to the number of partner in the channel
|
||||
self.flush_model()
|
||||
self.env['mail.channel.member'].flush_model()
|
||||
self.env['discuss.channel.member'].flush_model()
|
||||
self.env.cr.execute("""
|
||||
SELECT M.channel_id
|
||||
FROM mail_channel C, mail_channel_member M
|
||||
FROM discuss_channel C, discuss_channel_member M
|
||||
WHERE M.channel_id = C.id
|
||||
AND M.partner_id IN %s
|
||||
AND C.channel_type LIKE 'chat'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM mail_channel_member M2
|
||||
FROM discuss_channel_member M2
|
||||
WHERE M2.channel_id = C.id
|
||||
AND M2.partner_id NOT IN %s
|
||||
)
|
||||
@@ -942,7 +942,7 @@ class Channel(models.Model):
|
||||
channel = self.browse(result[0].get('channel_id'))
|
||||
# pin up the channel for the current partner
|
||||
if pin:
|
||||
self.env['mail.channel.member'].search([('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', channel.id)]).write({
|
||||
self.env['discuss.channel.member'].search([('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', channel.id)]).write({
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': fields.Datetime.now(),
|
||||
})
|
||||
@@ -971,7 +971,7 @@ class Channel(models.Model):
|
||||
:param state : the new status of the session for the current user.
|
||||
"""
|
||||
domain = [('partner_id', '=', self.env.user.partner_id.id), ('channel_id', 'in', self.ids)]
|
||||
for session_state in self.env['mail.channel.member'].search(domain):
|
||||
for session_state in self.env['discuss.channel.member'].search(domain):
|
||||
if not state:
|
||||
state = session_state.fold_state
|
||||
if session_state.fold_state == 'open':
|
||||
@@ -989,21 +989,21 @@ class Channel(models.Model):
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.record/insert', {
|
||||
'Thread': {
|
||||
'id': session_state.channel_id.id,
|
||||
'model': 'mail.channel',
|
||||
'model': 'discuss.channel',
|
||||
'serverFoldState': state,
|
||||
}
|
||||
})
|
||||
|
||||
def channel_pin(self, pinned=False):
|
||||
self.ensure_one()
|
||||
member = self.env['mail.channel.member'].search(
|
||||
member = self.env['discuss.channel.member'].search(
|
||||
[('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', self.id), ('is_pinned', '!=', pinned)])
|
||||
if member:
|
||||
member.write({'is_pinned': pinned})
|
||||
if not pinned:
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.channel/unpin', {'id': self.id})
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'discuss.channel/unpin', {'id': self.id})
|
||||
else:
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.channel/legacy_insert', self.channel_info()[0])
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'discuss.channel/legacy_insert', self.channel_info()[0])
|
||||
|
||||
def _channel_seen(self, last_message_id=None, allow_older=False):
|
||||
"""
|
||||
@@ -1015,7 +1015,7 @@ class Channel(models.Model):
|
||||
as the last seen message.
|
||||
"""
|
||||
self.ensure_one()
|
||||
domain = ["&", ("model", "=", "mail.channel"), ("res_id", "in", self.ids)]
|
||||
domain = ["&", ("model", "=", "discuss.channel"), ("res_id", "in", self.ids)]
|
||||
if last_message_id:
|
||||
domain = expression.AND([domain, [('id', '<=', int(last_message_id))]])
|
||||
last_message = (
|
||||
@@ -1031,7 +1031,7 @@ class Channel(models.Model):
|
||||
'partner_id': self.env.user.partner_id.id,
|
||||
}
|
||||
target = self if self.channel_type == 'chat' else self.env.user.partner_id
|
||||
self.env['bus.bus']._sendone(target, 'mail.channel.member/seen', data)
|
||||
self.env['bus.bus']._sendone(target, 'discuss.channel.member/seen', data)
|
||||
return last_message.id
|
||||
|
||||
def _set_last_seen_message(self, last_message, allow_older=False):
|
||||
@@ -1049,7 +1049,7 @@ class Channel(models.Model):
|
||||
[('seen_message_id', '<', last_message.id)]
|
||||
])
|
||||
])
|
||||
member = self.env['mail.channel.member'].search(channel_member_domain)
|
||||
member = self.env['discuss.channel.member'].search(channel_member_domain)
|
||||
member.write({
|
||||
'fetched_message_id': max(member.fetched_message_id.id, last_message.id),
|
||||
'seen_message_id': last_message.id,
|
||||
@@ -1065,14 +1065,14 @@ class Channel(models.Model):
|
||||
if channel.channel_type != 'chat':
|
||||
return
|
||||
last_message_id = channel.message_ids.ids[0] # zero is the index of the last message
|
||||
member = self.env['mail.channel.member'].search([('channel_id', '=', channel.id), ('partner_id', '=', self.env.user.partner_id.id)], limit=1)
|
||||
member = self.env['discuss.channel.member'].search([('channel_id', '=', channel.id), ('partner_id', '=', self.env.user.partner_id.id)], limit=1)
|
||||
if member.fetched_message_id.id == last_message_id:
|
||||
# last message fetched by user is already up-to-date
|
||||
return
|
||||
member.write({
|
||||
'fetched_message_id': last_message_id,
|
||||
})
|
||||
self.env['bus.bus']._sendone(channel, 'mail.channel.member/fetched', {
|
||||
self.env['bus.bus']._sendone(channel, 'discuss.channel.member/fetched', {
|
||||
'channel_id': channel.id,
|
||||
'id': member.id,
|
||||
'last_message_id': last_message_id,
|
||||
@@ -1081,7 +1081,7 @@ class Channel(models.Model):
|
||||
|
||||
def channel_set_custom_name(self, name):
|
||||
self.ensure_one()
|
||||
member = self.env['mail.channel.member'].search([('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', self.id)])
|
||||
member = self.env['discuss.channel.member'].search([('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', self.id)])
|
||||
member.write({'custom_channel_name': name})
|
||||
self.env['bus.bus']._sendone(member.partner_id, 'mail.record/insert', {
|
||||
'Channel': {
|
||||
@@ -1096,7 +1096,7 @@ class Channel(models.Model):
|
||||
self.env['bus.bus']._sendone(self, 'mail.record/insert', {
|
||||
'Thread': {
|
||||
'id': self.id,
|
||||
'model': 'mail.channel',
|
||||
'model': 'discuss.channel',
|
||||
'name': name,
|
||||
}
|
||||
})
|
||||
@@ -1108,7 +1108,7 @@ class Channel(models.Model):
|
||||
'Thread': {
|
||||
'id': self.id,
|
||||
'description': description,
|
||||
'model': 'mail.channel',
|
||||
'model': 'discuss.channel',
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1139,7 +1139,7 @@ class Channel(models.Model):
|
||||
}
|
||||
new_channel.message_post(body=notification, message_type="notification", subtype_xmlid="mail.mt_comment")
|
||||
channel_info = new_channel.channel_info()[0]
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.channel/legacy_insert', channel_info)
|
||||
self.env['bus.bus']._sendone(self.env.user.partner_id, 'discuss.channel/legacy_insert', channel_info)
|
||||
return channel_info
|
||||
|
||||
@api.model
|
||||
@@ -1203,22 +1203,22 @@ class Channel(models.Model):
|
||||
self.env.cr.execute("""
|
||||
SELECT res_id AS id, MAX(id) AS message_id
|
||||
FROM mail_message
|
||||
WHERE model = 'mail.channel' AND res_id IN %s
|
||||
WHERE model = 'discuss.channel' AND res_id IN %s
|
||||
GROUP BY res_id
|
||||
""", (tuple(self.ids),))
|
||||
return self.env.cr.dictfetchall()
|
||||
|
||||
def load_more_members(self, known_member_ids):
|
||||
self.ensure_one()
|
||||
unknown_members = self.env['mail.channel.member'].search(
|
||||
unknown_members = self.env['discuss.channel.member'].search(
|
||||
domain=[('id', 'not in', known_member_ids), ('channel_id', '=', self.id)],
|
||||
limit=100
|
||||
)
|
||||
count = self.env['mail.channel.member'].search_count(
|
||||
count = self.env['discuss.channel.member'].search_count(
|
||||
domain=[('channel_id', '=', self.id)],
|
||||
)
|
||||
return {
|
||||
'channelMembers': [('insert', list(unknown_members._mail_channel_member_format().values()))],
|
||||
'channelMembers': [('insert', list(unknown_members._discuss_channel_member_format().values()))],
|
||||
'memberCount': count,
|
||||
}
|
||||
|
||||
@@ -1236,7 +1236,7 @@ class Channel(models.Model):
|
||||
written in this channel.
|
||||
`content` is HTML, dynamic parts should be escaped by the caller.
|
||||
"""
|
||||
self.env['bus.bus']._sendone(partner_to, 'mail.channel/transient_message', {
|
||||
self.env['bus.bus']._sendone(partner_to, 'discuss.channel/transient_message', {
|
||||
'body': f"<span class='o_mail_notification'>{content}</span>",
|
||||
'model': self._name,
|
||||
'res_id': self.id,
|
||||
@@ -1247,7 +1247,7 @@ class Channel(models.Model):
|
||||
if self.channel_type == 'channel':
|
||||
msg = _("You are in channel <b>#%s</b>.", html_escape(self.name))
|
||||
else:
|
||||
all_channel_members = self.env['mail.channel.member'].with_context(active_test=False)
|
||||
all_channel_members = self.env['discuss.channel.member'].with_context(active_test=False)
|
||||
channel_members = all_channel_members.search([('partner_id', '!=', partner.id), ('channel_id', '=', self.id)])
|
||||
msg = _("You are in a private conversation with <b>@%s</b>.", _(" @").join(html_escape(member.partner_id.name or member.guest_id.name) for member in channel_members) if channel_members else _("Anonymous"))
|
||||
msg += self._execute_command_help_message_extra()
|
||||
@@ -1268,7 +1268,7 @@ class Channel(models.Model):
|
||||
self.channel_pin(False)
|
||||
|
||||
def execute_command_who(self, **kwargs):
|
||||
channel_members = self.env['mail.channel.member'].with_context(active_test=False).search([('partner_id', '!=', self.env.user.partner_id.id), ('channel_id', '=', self.id)])
|
||||
channel_members = self.env['discuss.channel.member'].with_context(active_test=False).search([('partner_id', '!=', self.env.user.partner_id.id), ('channel_id', '=', self.id)])
|
||||
members = [
|
||||
m.partner_id._get_html_link(title=f"@{m.partner_id.name}") if m.partner_id else f'<strong>@{html_escape(m.guest_id.name)}</strong>'
|
||||
for m in channel_members[:30]
|
||||
+30
-31
@@ -8,9 +8,8 @@ from odoo.osv import expression
|
||||
|
||||
|
||||
class ChannelMember(models.Model):
|
||||
_name = 'mail.channel.member'
|
||||
_name = 'discuss.channel.member'
|
||||
_description = 'Listeners of a Channel'
|
||||
_table = 'mail_channel_member'
|
||||
_rec_names_search = ['partner_id', 'guest_id']
|
||||
_bypass_create_check = {}
|
||||
|
||||
@@ -19,7 +18,7 @@ class ChannelMember(models.Model):
|
||||
guest_id = fields.Many2one(string="Guest", comodel_name='mail.guest', ondelete='cascade', readonly=True, index=True)
|
||||
partner_email = fields.Char('Email', related='partner_id.email', readonly=False)
|
||||
# channel
|
||||
channel_id = fields.Many2one('mail.channel', string='Channel', ondelete='cascade', readonly=True, required=True)
|
||||
channel_id = fields.Many2one('discuss.channel', string='Channel', ondelete='cascade', readonly=True, required=True)
|
||||
# state
|
||||
custom_channel_name = fields.Char('Custom channel name')
|
||||
fetched_message_id = fields.Many2one('mail.message', string='Last Fetched')
|
||||
@@ -31,8 +30,8 @@ class ChannelMember(models.Model):
|
||||
last_interest_dt = fields.Datetime("Last Interest", default=fields.Datetime.now, help="Contains the date and time of the last interesting event that happened in this channel for this partner. This includes: creating, joining, pinning, and new message posted.")
|
||||
last_seen_dt = fields.Datetime("Last seen date")
|
||||
# RTC
|
||||
rtc_session_ids = fields.One2many(string="RTC Sessions", comodel_name='mail.channel.rtc.session', inverse_name='channel_member_id')
|
||||
rtc_inviting_session_id = fields.Many2one('mail.channel.rtc.session', string='Ringing session')
|
||||
rtc_session_ids = fields.One2many(string="RTC Sessions", comodel_name='discuss.channel.rtc.session', inverse_name='channel_member_id')
|
||||
rtc_inviting_session_id = fields.Many2one('discuss.channel.rtc.session', string='Ringing session')
|
||||
|
||||
@api.depends('channel_id.message_ids', 'seen_message_id')
|
||||
def _compute_message_unread(self):
|
||||
@@ -41,18 +40,18 @@ class ChannelMember(models.Model):
|
||||
self.flush_recordset(['channel_id', 'seen_message_id'])
|
||||
self.env.cr.execute("""
|
||||
SELECT count(mail_message.id) AS count,
|
||||
mail_channel_member.id
|
||||
discuss_channel_member.id
|
||||
FROM mail_message
|
||||
INNER JOIN mail_channel_member
|
||||
ON mail_channel_member.channel_id = mail_message.res_id
|
||||
WHERE mail_message.model = 'mail.channel'
|
||||
INNER JOIN discuss_channel_member
|
||||
ON discuss_channel_member.channel_id = mail_message.res_id
|
||||
WHERE mail_message.model = 'discuss.channel'
|
||||
AND mail_message.message_type NOT IN ('notification', 'user_notification')
|
||||
AND (
|
||||
mail_message.id > mail_channel_member.seen_message_id
|
||||
OR mail_channel_member.seen_message_id IS NULL
|
||||
mail_message.id > discuss_channel_member.seen_message_id
|
||||
OR discuss_channel_member.seen_message_id IS NULL
|
||||
)
|
||||
AND mail_channel_member.id IN %(ids)s
|
||||
GROUP BY mail_channel_member.id
|
||||
AND discuss_channel_member.id IN %(ids)s
|
||||
GROUP BY discuss_channel_member.id
|
||||
""", {'ids': tuple(self.ids)})
|
||||
unread_counter_by_member = {res['id']: res['count'] for res in self.env.cr.dictfetchall()}
|
||||
for member in self:
|
||||
@@ -64,8 +63,8 @@ class ChannelMember(models.Model):
|
||||
return [(record.id, record.partner_id.name or record.guest_id.name) for record in self]
|
||||
|
||||
def init(self):
|
||||
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS mail_channel_member_partner_unique ON %s (channel_id, partner_id) WHERE partner_id IS NOT NULL" % self._table)
|
||||
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS mail_channel_member_guest_unique ON %s (channel_id, guest_id) WHERE guest_id IS NOT NULL" % self._table)
|
||||
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS discuss_channel_member_partner_unique ON %s (channel_id, partner_id) WHERE partner_id IS NOT NULL" % self._table)
|
||||
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS discuss_channel_member_guest_unique ON %s (channel_id, guest_id) WHERE guest_id IS NOT NULL" % self._table)
|
||||
|
||||
_sql_constraints = [
|
||||
("partner_or_guest_exists", "CHECK((partner_id IS NOT NULL AND guest_id IS NULL) OR (partner_id IS NULL AND guest_id IS NOT NULL))", "A channel member must be a partner or a guest."),
|
||||
@@ -82,7 +81,7 @@ class ChannelMember(models.Model):
|
||||
if not self.env.is_admin() and not self.env.context.get('mail_create_bypass_create_check') is self._bypass_create_check:
|
||||
for vals in vals_list:
|
||||
if 'channel_id' in vals:
|
||||
channel_id = self.env['mail.channel'].browse(vals['channel_id'])
|
||||
channel_id = self.env['discuss.channel'].browse(vals['channel_id'])
|
||||
if not channel_id._can_invite(vals.get('partner_id')):
|
||||
raise AccessError(_('This user can not be added in this channel'))
|
||||
return super().create(vals_list)
|
||||
@@ -116,14 +115,14 @@ class ChannelMember(models.Model):
|
||||
:return: A record set containing the channel member if found, or an
|
||||
empty record set otherwise. In case of guest, the record is returned
|
||||
with the 'guest' record in the context.
|
||||
:rtype: mail.channel.member
|
||||
:rtype: discuss.channel.member
|
||||
"""
|
||||
if request.session.uid:
|
||||
return self.env['mail.channel.member'].sudo().search([('channel_id', '=', channel_id), ('partner_id', '=', self.env.user.partner_id.id)], limit=1)
|
||||
return self.env['discuss.channel.member'].sudo().search([('channel_id', '=', channel_id), ('partner_id', '=', self.env.user.partner_id.id)], limit=1)
|
||||
guest = self.env['mail.guest']._get_guest_from_request(request)
|
||||
if guest:
|
||||
return guest.env['mail.channel.member'].sudo().search([('channel_id', '=', channel_id), ('guest_id', '=', guest.id)], limit=1)
|
||||
return self.env['mail.channel.member'].sudo()
|
||||
return guest.env['discuss.channel.member'].sudo().search([('channel_id', '=', channel_id), ('guest_id', '=', guest.id)], limit=1)
|
||||
return self.env['discuss.channel.member'].sudo()
|
||||
|
||||
def _notify_typing(self, is_typing):
|
||||
""" Broadcast the typing notification to channel members
|
||||
@@ -131,13 +130,13 @@ class ChannelMember(models.Model):
|
||||
"""
|
||||
notifications = []
|
||||
for member in self:
|
||||
formatted_member = member._mail_channel_member_format().get(member)
|
||||
formatted_member = member._discuss_channel_member_format().get(member)
|
||||
formatted_member['isTyping'] = is_typing
|
||||
notifications.append([member.channel_id, 'mail.channel.member/typing_status', formatted_member])
|
||||
notifications.append([member.channel_id.uuid, 'mail.channel.member/typing_status', formatted_member]) # notify livechat users
|
||||
notifications.append([member.channel_id, 'discuss.channel.member/typing_status', formatted_member])
|
||||
notifications.append([member.channel_id.uuid, 'discuss.channel.member/typing_status', formatted_member]) # notify livechat users
|
||||
self.env['bus.bus']._sendmany(notifications)
|
||||
|
||||
def _mail_channel_member_format(self, fields=None):
|
||||
def _discuss_channel_member_format(self, fields=None):
|
||||
if not fields:
|
||||
fields = {'id': True, 'channel': {}, 'persona': {}}
|
||||
members_formatted_data = {}
|
||||
@@ -169,7 +168,7 @@ class ChannelMember(models.Model):
|
||||
check_rtc_session_ids = (check_rtc_session_ids or []) + self.rtc_session_ids.ids
|
||||
self.channel_id._rtc_cancel_invitations(member_ids=self.ids)
|
||||
self.rtc_session_ids.unlink()
|
||||
rtc_session = self.env['mail.channel.rtc.session'].create({'channel_member_id': self.id})
|
||||
rtc_session = self.env['discuss.channel.rtc.session'].create({'channel_member_id': self.id})
|
||||
current_rtc_sessions, outdated_rtc_sessions = self._rtc_sync_sessions(check_rtc_session_ids=check_rtc_session_ids)
|
||||
res = {
|
||||
'iceServers': self.env['mail.ice.server']._get_ice_servers() or False,
|
||||
@@ -183,7 +182,7 @@ class ChannelMember(models.Model):
|
||||
self.channel_id.message_post(body=_("%s started a live conference", self.partner_id.name or self.guest_id.name), message_type='notification')
|
||||
invited_members = self._rtc_invite_members()
|
||||
if invited_members:
|
||||
res['invitedMembers'] = [('insert', list(invited_members._mail_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))]
|
||||
res['invitedMembers'] = [('insert', list(invited_members._discuss_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))]
|
||||
return res
|
||||
|
||||
def _rtc_leave_call(self):
|
||||
@@ -204,7 +203,7 @@ class ChannelMember(models.Model):
|
||||
"""
|
||||
self.ensure_one()
|
||||
self.channel_id.rtc_session_ids._delete_inactive_rtc_sessions()
|
||||
check_rtc_sessions = self.env['mail.channel.rtc.session'].browse([int(check_rtc_session_id) for check_rtc_session_id in (check_rtc_session_ids or [])])
|
||||
check_rtc_sessions = self.env['discuss.channel.rtc.session'].browse([int(check_rtc_session_id) for check_rtc_session_id in (check_rtc_session_ids or [])])
|
||||
return self.channel_id.rtc_session_ids, check_rtc_sessions - self.channel_id.rtc_session_ids
|
||||
|
||||
def _rtc_invite_members(self, member_ids=None):
|
||||
@@ -222,7 +221,7 @@ class ChannelMember(models.Model):
|
||||
if member_ids:
|
||||
channel_member_domain = expression.AND([channel_member_domain, [('id', 'in', member_ids)]])
|
||||
invitation_notifications = []
|
||||
members = self.env['mail.channel.member'].search(channel_member_domain)
|
||||
members = self.env['discuss.channel.member'].search(channel_member_domain)
|
||||
for member in members:
|
||||
member.rtc_inviting_session_id = self.rtc_session_ids.id
|
||||
if member.partner_id:
|
||||
@@ -232,13 +231,13 @@ class ChannelMember(models.Model):
|
||||
invitation_notifications.append((target, 'mail.record/insert', {
|
||||
'Thread': {
|
||||
'id': self.channel_id.id,
|
||||
'model': 'mail.channel',
|
||||
'model': 'discuss.channel',
|
||||
'rtcInvitingSession': self.rtc_session_ids._mail_rtc_session_format(),
|
||||
}
|
||||
}))
|
||||
self.env['bus.bus']._sendmany(invitation_notifications)
|
||||
if members:
|
||||
channel_data = {'id': self.channel_id.id, 'model': 'mail.channel'}
|
||||
channel_data['invitedMembers'] = [('insert', list(members._mail_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))]
|
||||
channel_data = {'id': self.channel_id.id, 'model': 'discuss.channel'}
|
||||
channel_data['invitedMembers'] = [('insert', list(members._discuss_channel_member_format(fields={'id': True, 'channel': {}, 'persona': {'partner': {'id', 'name', 'im_status'}, 'guest': {'id', 'name', 'im_status'}}}).values()))]
|
||||
self.env['bus.bus']._sendone(self.channel_id, 'mail.record/insert', {'Thread': channel_data})
|
||||
return members
|
||||
+10
-10
@@ -8,12 +8,12 @@ from odoo import api, fields, models
|
||||
|
||||
|
||||
class MailRtcSession(models.Model):
|
||||
_name = 'mail.channel.rtc.session'
|
||||
_name = 'discuss.channel.rtc.session'
|
||||
_description = 'Mail RTC session'
|
||||
_rec_name = 'channel_member_id'
|
||||
|
||||
channel_member_id = fields.Many2one('mail.channel.member', required=True, ondelete='cascade')
|
||||
channel_id = fields.Many2one('mail.channel', related='channel_member_id.channel_id', store=True, readonly=True)
|
||||
channel_member_id = fields.Many2one('discuss.channel.member', required=True, ondelete='cascade')
|
||||
channel_id = fields.Many2one('discuss.channel', related='channel_member_id.channel_id', store=True, readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', related='channel_member_id.partner_id', string="Partner")
|
||||
guest_id = fields.Many2one('mail.guest', related='channel_member_id.guest_id')
|
||||
|
||||
@@ -32,7 +32,7 @@ class MailRtcSession(models.Model):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
rtc_sessions = super().create(vals_list)
|
||||
self.env['bus.bus']._sendmany([(channel, 'mail.channel/rtc_sessions_update', {
|
||||
self.env['bus.bus']._sendmany([(channel, 'discuss.channel/rtc_sessions_update', {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', sessions_data)],
|
||||
}) for channel, sessions_data in rtc_sessions._mail_rtc_session_format_by_channel().items()])
|
||||
@@ -46,13 +46,13 @@ class MailRtcSession(models.Model):
|
||||
# Note: invitation depends on field `rtc_inviting_session_id` so the cancel must be
|
||||
# done before the delete to be able to know who was invited.
|
||||
channel._rtc_cancel_invitations()
|
||||
notifications = [(channel, 'mail.channel/rtc_sessions_update', {
|
||||
notifications = [(channel, 'discuss.channel/rtc_sessions_update', {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': session_data['id']} for session_data in sessions_data])],
|
||||
}) for channel, sessions_data in self._mail_rtc_session_format_by_channel().items()]
|
||||
for rtc_session in self:
|
||||
target = rtc_session.guest_id or rtc_session.partner_id
|
||||
notifications.append((target, 'mail.channel.rtc.session/ended', {'sessionId': rtc_session.id}))
|
||||
notifications.append((target, 'discuss.channel.rtc.session/ended', {'sessionId': rtc_session.id}))
|
||||
self.env['bus.bus']._sendmany(notifications)
|
||||
return super().unlink()
|
||||
|
||||
@@ -85,16 +85,16 @@ class MailRtcSession(models.Model):
|
||||
guarantees that the sender is the current guest or partner.
|
||||
|
||||
:param notifications: list of tuple with the following elements:
|
||||
- target_session_ids: a list of mail.channel.rtc.session ids
|
||||
- target_session_ids: a list of discuss.channel.rtc.session ids
|
||||
- content: a string with the content to be sent to the targets
|
||||
"""
|
||||
self.ensure_one()
|
||||
payload_by_target = defaultdict(lambda: {'sender': self.id, 'notifications': []})
|
||||
for target_session_ids, content in notifications:
|
||||
for target_session in self.env['mail.channel.rtc.session'].browse(target_session_ids).exists():
|
||||
for target_session in self.env['discuss.channel.rtc.session'].browse(target_session_ids).exists():
|
||||
target = target_session.guest_id or target_session.partner_id
|
||||
payload_by_target[target]['notifications'].append(content)
|
||||
return self.env['bus.bus']._sendmany([(target, 'mail.channel.rtc.session/peer_notification', payload) for target, payload in payload_by_target.items()])
|
||||
return self.env['bus.bus']._sendmany([(target, 'discuss.channel.rtc.session/peer_notification', payload) for target, payload in payload_by_target.items()])
|
||||
|
||||
def _mail_rtc_session_format(self, fields=None):
|
||||
self.ensure_one()
|
||||
@@ -104,7 +104,7 @@ class MailRtcSession(models.Model):
|
||||
if 'id' in fields:
|
||||
vals['id'] = self.id
|
||||
if 'channelMember' in fields:
|
||||
vals['channelMember'] = self.channel_member_id._mail_channel_member_format(fields=fields.get('channelMember')).get(self.channel_member_id)
|
||||
vals['channelMember'] = self.channel_member_id._discuss_channel_member_format(fields=fields.get('channelMember')).get(self.channel_member_id)
|
||||
if 'isCameraOn' in fields:
|
||||
vals['isCameraOn'] = self.is_camera_on
|
||||
if 'isDeaf' in fields:
|
||||
@@ -40,8 +40,8 @@ class IrAttachment(models.Model):
|
||||
|
||||
def _delete_and_notify(self):
|
||||
for attachment in self:
|
||||
if attachment.res_model == 'mail.channel' and attachment.res_id:
|
||||
target = self.env['mail.channel'].browse(attachment.res_id)
|
||||
if attachment.res_model == 'discuss.channel' and attachment.res_id:
|
||||
target = self.env['discuss.channel'].browse(attachment.res_id)
|
||||
else:
|
||||
target = self.env.user.partner_id
|
||||
self.env['bus.bus']._sendone(target, 'ir.attachment/delete', {
|
||||
|
||||
@@ -23,16 +23,16 @@ class IrWebsocket(models.AbstractModel):
|
||||
req = request or wsrequest
|
||||
channels = list(channels) # do not alter original list
|
||||
guest_sudo = self.env['mail.guest']._get_guest_from_request(req).sudo()
|
||||
mail_channels = self.env['mail.channel']
|
||||
discuss_channels = self.env['discuss.channel']
|
||||
if req.session.uid:
|
||||
partner = self.env.user.partner_id
|
||||
mail_channels = partner.channel_ids
|
||||
discuss_channels = partner.channel_ids
|
||||
channels.append(partner)
|
||||
elif guest_sudo:
|
||||
mail_channels = guest_sudo.channel_ids
|
||||
discuss_channels = guest_sudo.channel_ids
|
||||
channels.append(guest_sudo)
|
||||
for mail_channel in mail_channels:
|
||||
channels.append(mail_channel)
|
||||
for discuss_channel in discuss_channels:
|
||||
channels.append(discuss_channel)
|
||||
return super()._build_bus_channel_list(channels)
|
||||
|
||||
def _update_bus_presence(self, inactivity_period, im_status_ids_by_model):
|
||||
|
||||
@@ -28,7 +28,7 @@ class MailGuest(models.Model):
|
||||
country_id = fields.Many2one(string="Country", comodel_name='res.country')
|
||||
lang = fields.Selection(string="Language", selection=_lang_get)
|
||||
timezone = fields.Selection(string="Timezone", selection=_tz_get)
|
||||
channel_ids = fields.Many2many(string="Channels", comodel_name='mail.channel', relation='mail_channel_member', column1='guest_id', column2='channel_id', copy=False)
|
||||
channel_ids = fields.Many2many(string="Channels", comodel_name='discuss.channel', relation='discuss_channel_member', column1='guest_id', column2='channel_id', copy=False)
|
||||
im_status = fields.Char('IM Status', compute='_compute_im_status')
|
||||
|
||||
def _compute_im_status(self):
|
||||
|
||||
@@ -43,8 +43,8 @@ class LinkPreview(models.Model):
|
||||
if not link_previews:
|
||||
return
|
||||
guest = self.env['mail.guest']._get_guest_from_context()
|
||||
if message.model == 'mail.channel' and message.res_id:
|
||||
target = self.env['mail.channel'].browse(message.res_id)
|
||||
if message.model == 'discuss.channel' and message.res_id:
|
||||
target = self.env['discuss.channel'].browse(message.res_id)
|
||||
elif self.env.user._is_public() and guest:
|
||||
target = guest
|
||||
else:
|
||||
@@ -67,8 +67,8 @@ class LinkPreview(models.Model):
|
||||
notifications = []
|
||||
guest = self.env['mail.guest']._get_guest_from_context()
|
||||
for link_preview in self:
|
||||
if link_preview.message_id.model == 'mail.channel' and link_preview.message_id.res_id:
|
||||
target = self.env['mail.channel'].browse(link_preview.message_id.res_id)
|
||||
if link_preview.message_id.model == 'discuss.channel' and link_preview.message_id.res_id:
|
||||
target = self.env['discuss.channel'].browse(link_preview.message_id.res_id)
|
||||
elif self.env.user._is_public() and guest:
|
||||
target = guest
|
||||
else:
|
||||
|
||||
@@ -890,7 +890,7 @@ class Message(models.Model):
|
||||
'message': {'id': message_sudo.id},
|
||||
'partners': [{'id': partner.id, 'name': partner.name} for partner in reactions.partner_id],
|
||||
} for content, reactions in reactions_per_content.items()]
|
||||
if format_reply and message_sudo.model == 'mail.channel' and message_sudo.parent_id:
|
||||
if format_reply and message_sudo.model == 'discuss.channel' and message_sudo.parent_id:
|
||||
vals['parentMessage'] = message_sudo.parent_id.message_format(format_reply=False)[0]
|
||||
allowed_tracking_ids = message_sudo.tracking_value_ids.filtered(lambda tracking: not tracking.field_groups or self.env.is_superuser() or self.user_has_groups(tracking.field_groups))
|
||||
vals.update({
|
||||
|
||||
@@ -6,7 +6,7 @@ from odoo import models
|
||||
|
||||
class ResGroups(models.Model):
|
||||
""" Update of res.groups class
|
||||
- if adding users from a group, check mail.channels linked to this user
|
||||
- if adding users from a group, check discuss.channels linked to this user
|
||||
group and subscribe them. This is done by overriding the write method.
|
||||
"""
|
||||
_name = 'res.groups'
|
||||
@@ -19,5 +19,5 @@ class ResGroups(models.Model):
|
||||
# form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
|
||||
user_ids = [command[1] for command in vals['users'] if command[0] == 4]
|
||||
user_ids += [id for command in vals['users'] if command[0] == 6 for id in command[2]]
|
||||
self.env['mail.channel'].search([('group_ids', 'in', self._ids)])._subscribe_users_automatically()
|
||||
self.env['discuss.channel'].search([('group_ids', 'in', self._ids)])._subscribe_users_automatically()
|
||||
return res
|
||||
|
||||
@@ -21,7 +21,7 @@ class Partner(models.Model):
|
||||
user_id = fields.Many2one(tracking=4)
|
||||
vat = fields.Char(tracking=5)
|
||||
# channels
|
||||
channel_ids = fields.Many2many('mail.channel', 'mail_channel_member', 'partner_id', 'channel_id', string='Channels', copy=False)
|
||||
channel_ids = fields.Many2many('discuss.channel', 'discuss_channel_member', 'partner_id', 'channel_id', string='Channels', copy=False)
|
||||
# tracked field used for chatter logging purposes
|
||||
# we need this to be readable inline as tracking messages use inline HTML nodes
|
||||
contact_address_inline = fields.Char(compute='_compute_contact_address_inline', string='Inlined Complete Address', tracking=True)
|
||||
@@ -267,16 +267,16 @@ class Partner(models.Model):
|
||||
def _get_channels_as_member(self):
|
||||
"""Returns the channels of the partner."""
|
||||
self.ensure_one()
|
||||
channels = self.env['mail.channel']
|
||||
channels = self.env['discuss.channel']
|
||||
# get the channels and groups
|
||||
channels |= self.env['mail.channel'].search([
|
||||
channels |= self.env['discuss.channel'].search([
|
||||
('channel_type', 'in', ('channel', 'group')),
|
||||
('channel_partner_ids', 'in', [self.id]),
|
||||
])
|
||||
# get the pinned direct messages
|
||||
channels |= self.env['mail.channel'].search([
|
||||
channels |= self.env['discuss.channel'].search([
|
||||
('channel_type', '=', 'chat'),
|
||||
('channel_member_ids', 'in', self.env['mail.channel.member'].sudo()._search([
|
||||
('channel_member_ids', 'in', self.env['discuss.channel.member'].sudo()._search([
|
||||
('partner_id', '=', self.id),
|
||||
('is_pinned', '=', True),
|
||||
])),
|
||||
@@ -301,7 +301,7 @@ class Partner(models.Model):
|
||||
[('user_ids.share', '=', False)],
|
||||
])
|
||||
if channel_id:
|
||||
channel = self.env['mail.channel'].search([('id', '=', int(channel_id))])
|
||||
channel = self.env['discuss.channel'].search([('id', '=', int(channel_id))])
|
||||
domain = expression.AND([domain, [('channel_ids', 'not in', channel.id)]])
|
||||
if channel.group_public_id:
|
||||
domain = expression.AND([domain, [('user_ids.groups_id', 'in', channel.group_public_id.id)]])
|
||||
@@ -342,10 +342,10 @@ class Partner(models.Model):
|
||||
partners |= self.browse(query)
|
||||
partners_format = partners.mail_partner_format()
|
||||
if channel_id:
|
||||
member_by_partner = {member.partner_id: member for member in self.env['mail.channel.member'].search([('channel_id', '=', channel_id), ('partner_id', 'in', partners.ids)])}
|
||||
member_by_partner = {member.partner_id: member for member in self.env['discuss.channel.member'].search([('channel_id', '=', channel_id), ('partner_id', 'in', partners.ids)])}
|
||||
for partner in partners:
|
||||
partners_format.get(partner)['persona'] = {
|
||||
'channelMembers': [('insert', member_by_partner.get(partner)._mail_channel_member_format(fields={'id': True, 'channel': {'id'}, 'persona': {'partner': {'id'}}}).get(member_by_partner.get(partner)))],
|
||||
'channelMembers': [('insert', member_by_partner.get(partner)._discuss_channel_member_format(fields={'id': True, 'channel': {'id'}, 'persona': {'partner': {'id'}}}).get(member_by_partner.get(partner)))],
|
||||
}
|
||||
return list(partners_format.values())
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class Users(models.Model):
|
||||
- make a new user follow itself
|
||||
- add a welcome message
|
||||
- add suggestion preference
|
||||
- if adding groups to a user, check mail.channels linked to this user
|
||||
- if adding groups to a user, check discuss.channels linked to this user
|
||||
group, and the user. This is done by overriding the write method.
|
||||
"""
|
||||
_name = 'res.users'
|
||||
@@ -107,8 +107,8 @@ class Users(models.Model):
|
||||
subtype_xmlid='mail.mt_note'
|
||||
)
|
||||
# Auto-subscribe to channels unless skip explicitly requested
|
||||
if not self.env.context.get('mail_channel_nosubscribe'):
|
||||
self.env['mail.channel'].search([('group_ids', 'in', users.groups_id.ids)])._subscribe_users_automatically()
|
||||
if not self.env.context.get('discuss_channel_nosubscribe'):
|
||||
self.env['discuss.channel'].search([('group_ids', 'in', users.groups_id.ids)])._subscribe_users_automatically()
|
||||
return users
|
||||
|
||||
def write(self, vals):
|
||||
@@ -172,9 +172,9 @@ class Users(models.Model):
|
||||
# form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
|
||||
user_group_ids = [command[1] for command in vals['groups_id'] if command[0] == 4]
|
||||
user_group_ids += [id for command in vals['groups_id'] if command[0] == 6 for id in command[2]]
|
||||
self.env['mail.channel'].search([('group_ids', 'in', user_group_ids)])._subscribe_users_automatically()
|
||||
self.env['discuss.channel'].search([('group_ids', 'in', user_group_ids)])._subscribe_users_automatically()
|
||||
elif sel_groups:
|
||||
self.env['mail.channel'].search([('group_ids', 'in', sel_groups)])._subscribe_users_automatically()
|
||||
self.env['discuss.channel'].search([('group_ids', 'in', sel_groups)])._subscribe_users_automatically()
|
||||
return write_res
|
||||
|
||||
def unlink(self):
|
||||
@@ -251,7 +251,7 @@ class Users(models.Model):
|
||||
public channels are mailing list (e-mail based) and so users should always receive
|
||||
updates from public channels until they manually un-subscribe themselves.
|
||||
"""
|
||||
current_cm = self.env['mail.channel.member'].sudo().search([
|
||||
current_cm = self.env['discuss.channel.member'].sudo().search([
|
||||
('partner_id', 'in', self.partner_id.ids),
|
||||
])
|
||||
current_cm.filtered(
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from . import mail_channel
|
||||
from . import mail_channel_member
|
||||
from . import discuss_channel
|
||||
from . import discuss_channel_member
|
||||
from . import mail_message
|
||||
|
||||
@@ -3,7 +3,7 @@ from odoo import models
|
||||
from odoo.tools import populate
|
||||
|
||||
class Channel(models.Model):
|
||||
_inherit = 'mail.channel'
|
||||
_inherit = 'discuss.channel'
|
||||
_populate_dependencies = ["res.partner"]
|
||||
_populate_sizes = {'small': 10, 'medium': 100, 'large': 500}
|
||||
|
||||
+5
-5
@@ -3,22 +3,22 @@ from odoo import models
|
||||
from odoo.tools import populate
|
||||
|
||||
class ChannelMember(models.Model):
|
||||
_inherit = "mail.channel.member"
|
||||
_populate_dependencies = ["res.partner", "mail.channel"]
|
||||
_inherit = "discuss.channel.member"
|
||||
_populate_dependencies = ["res.partner", "discuss.channel"]
|
||||
_populate_sizes = {'small': 10, 'medium': 100, 'large': 1000}
|
||||
|
||||
def _populate_factories(self):
|
||||
partner_ids = self.env.registry.populated_models["res.partner"]
|
||||
channel_ids = self.env.registry.populated_models["mail.channel"]
|
||||
channel_ids = self.env.registry.populated_models["discuss.channel"]
|
||||
return [
|
||||
("partner_id", populate.randomize(partner_ids)),
|
||||
("channel_id", populate.randomize(channel_ids)),
|
||||
]
|
||||
|
||||
def _populate(self, size):
|
||||
channel_ids = self.env.registry.populated_models["mail.channel"]
|
||||
channel_ids = self.env.registry.populated_models["discuss.channel"]
|
||||
for channel_id in channel_ids:
|
||||
self.env['mail.channel.member'].create({
|
||||
self.env['discuss.channel.member'].create({
|
||||
'partner_id': self.env.ref('base.user_admin').partner_id.id,
|
||||
'channel_id': channel_id
|
||||
})
|
||||
@@ -4,11 +4,11 @@ from odoo.tools import populate
|
||||
|
||||
class Message(models.Model):
|
||||
_inherit = 'mail.message'
|
||||
_populate_dependencies = ['mail.channel', 'mail.channel.member', 'res.partner']
|
||||
_populate_dependencies = ['discuss.channel', 'discuss.channel.member', 'res.partner']
|
||||
_populate_sizes = {'small': 1000, 'medium': 10000, 'large': 500000}
|
||||
|
||||
def _populate_factories(self):
|
||||
channel_ids = self.env.registry.populated_models['mail.channel']
|
||||
channel_ids = self.env.registry.populated_models['discuss.channel']
|
||||
|
||||
def get_author_id(values, counter, random):
|
||||
channel = self.env[values['model']].browse(values['res_id'])
|
||||
@@ -17,7 +17,7 @@ class Message(models.Model):
|
||||
|
||||
return [
|
||||
('body', populate.constant('message_body_{counter}')),
|
||||
('message_type', populate.constant('comment')), ('model', populate.constant('mail.channel')),
|
||||
('message_type', populate.constant('comment')), ('model', populate.constant('discuss.channel')),
|
||||
('res_id', populate.randomize(channel_ids)),
|
||||
('author_id', populate.compute(get_author_id)),
|
||||
]
|
||||
|
||||
@@ -15,14 +15,14 @@ access_mail_followers_system,mail.followers.system,model_mail_followers,base.gro
|
||||
access_mail_notification_portal,mail.notification.portal,model_mail_notification,base.group_portal,1,0,0,0
|
||||
access_mail_notification_user,mail.notification.user,model_mail_notification,base.group_user,1,1,1,0
|
||||
access_mail_notification_system, mail.notification.system,model_mail_notification,base.group_system,1,1,1,1
|
||||
access_mail_channel_all,mail.group.all,model_mail_channel,,1,0,0,0
|
||||
access_mail_channel_user,mail.group.user,model_mail_channel,base.group_user,1,1,1,0
|
||||
access_mail_channel_admin,mail.group.system,model_mail_channel,base.group_system,1,1,1,1
|
||||
access_mail_channel_member_public,mail.channel.member.public,model_mail_channel_member,base.group_public,1,0,0,0
|
||||
access_mail_channel_member_portal,mail.channel.member.portal,model_mail_channel_member,base.group_portal,1,1,1,1
|
||||
access_mail_channel_member_user,mail.channel.member.user,model_mail_channel_member,base.group_user,1,1,1,1
|
||||
access_mail_channel_rtc_session_all,mail.channel.rtc.session.all,model_mail_channel_rtc_session,,0,0,0,0
|
||||
access_mail_channel_rtc_session_system,mail.channel.rtc.session.system,model_mail_channel_rtc_session,base.group_system,1,1,1,1
|
||||
access_discuss_channel_all,discuss.channel.all,model_discuss_channel,,1,0,0,0
|
||||
access_discuss_channel_user,discuss.channel.user,model_discuss_channel,base.group_user,1,1,1,0
|
||||
access_discuss_channel_admin,discuss.channel.system,model_discuss_channel,base.group_system,1,1,1,1
|
||||
access_discuss_channel_member_public,discuss.channel.member.public,model_discuss_channel_member,base.group_public,1,0,0,0
|
||||
access_discuss_channel_member_portal,discuss.channel.member.portal,model_discuss_channel_member,base.group_portal,1,1,1,1
|
||||
access_discuss_channel_member_user,discuss.channel.member.user,model_discuss_channel_member,base.group_user,1,1,1,1
|
||||
access_discuss_channel_rtc_session_all,discuss.channel.rtc.session.all,model_discuss_channel_rtc_session,,0,0,0,0
|
||||
access_discuss_channel_rtc_session_system,discuss.channel.rtc.session.system,model_discuss_channel_rtc_session,base.group_system,1,1,1,1
|
||||
access_mail_alias_all,mail.alias.all,model_mail_alias,,1,0,0,0
|
||||
access_mail_alias_user,mail.alias.user,model_mail_alias,base.group_user,1,0,0,0
|
||||
access_mail_alias_system,mail.alias.system,model_mail_alias,base.group_system,1,1,1,1
|
||||
|
||||
|
@@ -2,9 +2,9 @@
|
||||
<odoo noupdate="1">
|
||||
|
||||
<!-- RULES -->
|
||||
<record id="mail_channel_rule" model="ir.rule">
|
||||
<field name="name">Mail.channel: access only public and joined groups</field>
|
||||
<field name="model_id" ref="model_mail_channel"/>
|
||||
<record id="discuss_channel_rule" model="ir.rule">
|
||||
<field name="name">discuss.channel: access only public and joined groups</field>
|
||||
<field name="model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="groups" eval="[Command.link(ref('base.group_user')), Command.link(ref('base.group_portal')), Command.link(ref('base.group_public'))]"/>
|
||||
<field name="domain_force">[
|
||||
'|',
|
||||
@@ -20,16 +20,16 @@
|
||||
<field name="perm_create" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_channel_admin" model="ir.rule">
|
||||
<field name="name">Mail.channel: admin full access</field>
|
||||
<field name="model_id" ref="model_mail_channel"/>
|
||||
<record id="discuss_channel_admin" model="ir.rule">
|
||||
<field name="name">discuss.channel: admin full access</field>
|
||||
<field name="model_id" ref="mail.model_discuss_channel"/>
|
||||
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
</record>
|
||||
|
||||
<record id="ir_rule_mail_channel_member_group_user" model="ir.rule">
|
||||
<field name="name">mail.channel.member: write its own entries</field>
|
||||
<field name="model_id" ref="model_mail_channel_member"/>
|
||||
<record id="ir_rule_discuss_channel_member_group_user" model="ir.rule">
|
||||
<field name="name">discuss.channel.member: write its own entries</field>
|
||||
<field name="model_id" ref="mail.model_discuss_channel_member"/>
|
||||
<field name="groups" eval="[(4, ref('base.group_user')), (4, ref('base.group_portal'))]"/>
|
||||
<field name="domain_force">[
|
||||
'|',
|
||||
@@ -48,9 +48,9 @@
|
||||
<field name="perm_unlink" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="ir_rule_mail_channel_member_group_system" model="ir.rule">
|
||||
<field name="name">mail.channel.member: admin can manipulate all entries</field>
|
||||
<field name="model_id" ref="model_mail_channel_member"/>
|
||||
<record id="ir_rule_discuss_channel_member_group_system" model="ir.rule">
|
||||
<field name="name">discuss.channel.member: admin can manipulate all entries</field>
|
||||
<field name="model_id" ref="mail.model_discuss_channel_member"/>
|
||||
<field name="groups" eval="[Command.link(ref('base.group_system'))]"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
</record>
|
||||
|
||||
@@ -53,9 +53,9 @@ export class AttachmentList extends Component {
|
||||
!this.env.inComposer &&
|
||||
!this.env.inChatter &&
|
||||
!attachment.accessToken &&
|
||||
attachment.originThread?.model === "mail.channel"
|
||||
attachment.originThread?.model === "discuss.channel"
|
||||
) {
|
||||
return `/mail/channel/${attachment.originThread?.id}/image/${attachment.id}/${this.imagesWidth}x${imagesHeight}`;
|
||||
return `/discuss/channel/${attachment.originThread?.id}/image/${attachment.id}/${this.imagesWidth}x${imagesHeight}`;
|
||||
}
|
||||
const accessToken = attachment.accessToken ? `?access_token=${attachment.accessToken}` : "";
|
||||
return `/web/image/${attachment.id}/${this.imagesWidth}x${imagesHeight}${accessToken}`;
|
||||
|
||||
@@ -27,7 +27,7 @@ export class Attachment {
|
||||
}
|
||||
|
||||
get isDeletable() {
|
||||
if (this.message && this.originThread?.model === "mail.channel") {
|
||||
if (this.message && this.originThread?.model === "discuss.channel") {
|
||||
return this.message.editable;
|
||||
}
|
||||
return true;
|
||||
@@ -89,8 +89,8 @@ export class Attachment {
|
||||
if (!this.isImage) {
|
||||
return "";
|
||||
}
|
||||
if (!this.accessToken && this.originThread?.model === "mail.channel") {
|
||||
return `/mail/channel/${this.originThread.id}/image/${this.id}`;
|
||||
if (!this.accessToken && this.originThread?.model === "discuss.channel") {
|
||||
return `/discuss/channel/${this.originThread.id}/image/${this.id}`;
|
||||
}
|
||||
const accessToken = this.accessToken ? `?access_token=${this.accessToken}` : "";
|
||||
return `/web/image/${this.id}${accessToken}`;
|
||||
@@ -102,8 +102,8 @@ export class Attachment {
|
||||
}
|
||||
if (this.isPdf) {
|
||||
const pdf_lib = "/web/static/lib/pdfjs/web/viewer.html?file=";
|
||||
if (!this.accessToken && this.originThread?.model === "mail.channel") {
|
||||
return `${pdf_lib}/mail/channel/${this.originThread.id}/attachment/${this.id}`;
|
||||
if (!this.accessToken && this.originThread?.model === "discuss.channel") {
|
||||
return `${pdf_lib}/discuss/channel/${this.originThread.id}/attachment/${this.id}`;
|
||||
}
|
||||
const accessToken = this.accessToken ? `?access_token%3D${this.accessToken}` : "";
|
||||
return `${pdf_lib}/web/content/${this.id}${accessToken}`;
|
||||
@@ -120,16 +120,16 @@ export class Attachment {
|
||||
}
|
||||
return `https://www.youtube.com/embed/${token}`;
|
||||
}
|
||||
if (!this.accessToken && this.originThread?.model === "mail.channel") {
|
||||
return `/mail/channel/${this.originThread.id}/attachment/${this.id}`;
|
||||
if (!this.accessToken && this.originThread?.model === "discuss.channel") {
|
||||
return `/discuss/channel/${this.originThread.id}/attachment/${this.id}`;
|
||||
}
|
||||
const accessToken = this.accessToken ? `?access_token=${this.accessToken}` : "";
|
||||
return `/web/content/${this.id}${accessToken}`;
|
||||
}
|
||||
|
||||
get downloadUrl() {
|
||||
if (!this.accessToken && this.originThread?.model === "mail.channel") {
|
||||
return `/mail/channel/${this.originThread.id}/attachment/${this.id}?download=true`;
|
||||
if (!this.accessToken && this.originThread?.model === "discuss.channel") {
|
||||
return `/discuss/channel/${this.originThread.id}/attachment/${this.id}?download=true`;
|
||||
}
|
||||
const accessToken = this.accessToken ? `access_token=${this.accessToken}&` : "";
|
||||
return `/web/content/ir.attachment/${this.id}/datas?${accessToken}download=true`;
|
||||
|
||||
@@ -471,7 +471,7 @@ export class Composer extends Component {
|
||||
notifyIsTyping(is_typing = true) {
|
||||
if (["chat", "channel", "group"].includes(this.thread?.type)) {
|
||||
this.messaging.rpc(
|
||||
"/mail/channel/notify_typing",
|
||||
"/discuss/channel/notify_typing",
|
||||
{
|
||||
channel_id: this.thread.id,
|
||||
is_typing,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { cleanTerm } from "@mail/utils/format";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
const commandRegistry = registry.category("mail.channel_commands");
|
||||
const commandRegistry = registry.category("discuss.channel_commands");
|
||||
|
||||
export class SuggestionService {
|
||||
constructor(env, services) {
|
||||
@@ -15,7 +15,7 @@ export class SuggestionService {
|
||||
/** @type {import("@mail/core/persona_service").PersonaService} */
|
||||
this.personaService = services["mail.persona"];
|
||||
/** @type {import("@mail/core/channel_member_service").ChannelMemberService} */
|
||||
this.channelMemberService = services["mail.channel.member"];
|
||||
this.channelMemberService = services["discuss.channel.member"];
|
||||
}
|
||||
|
||||
getSupportedDelimiters(thread) {
|
||||
@@ -63,14 +63,14 @@ export class SuggestionService {
|
||||
|
||||
async fetchThreads(term) {
|
||||
const suggestedThreads = await this.orm.call(
|
||||
"mail.channel",
|
||||
"discuss.channel",
|
||||
"get_mention_suggestions",
|
||||
[],
|
||||
{ search: term }
|
||||
);
|
||||
suggestedThreads.map((data) => {
|
||||
this.threadService.insert({
|
||||
model: "mail.channel",
|
||||
model: "discuss.channel",
|
||||
...data,
|
||||
});
|
||||
});
|
||||
@@ -352,7 +352,7 @@ export class SuggestionService {
|
||||
}
|
||||
|
||||
export const suggestionService = {
|
||||
dependencies: ["orm", "mail.store", "mail.thread", "mail.persona", "mail.channel.member"],
|
||||
dependencies: ["orm", "mail.store", "mail.thread", "mail.persona", "discuss.channel.member"],
|
||||
start(env, services) {
|
||||
return new SuggestionService(env, services);
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { registry } from "@web/core/registry";
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
|
||||
const commandRegistry = registry.category("mail.channel_commands");
|
||||
const commandRegistry = registry.category("discuss.channel_commands");
|
||||
|
||||
commandRegistry
|
||||
.add("help", {
|
||||
|
||||
@@ -30,6 +30,6 @@ export class ChannelMember {
|
||||
}
|
||||
|
||||
get thread() {
|
||||
return this._store.threads[createLocalId("mail.channel", this.threadId)];
|
||||
return this._store.threads[createLocalId("discuss.channel", this.threadId)];
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user