[MERGE] (im/website)_livechat : set session as inactive after closing it

PURPOSE

If a visitor closes the livechat window, he is redirected on rating / feedback
/ send_transcript screen but he cannot go back to the conversation unless he
reloads the whole page.

Conversation should be considered as inactive after the first click on X.

SPECIFICATIONS

This merge holds two main commits

  * move close livechat session to base livechat module in order to be able
    to flag the livechat as inactive when the visitor leave the conversation;
  * set livechat inactive _onCloseChatWindow: closes the conversation (set
    as livechat inactive and send the 'has left conversation' message) at
    first time the visitor closes the conversation;

See sub commits for more details.

LINKS

Task ID: 2120210
Community PR odoo/odoo#39939
Upgrade odoo/upgrade#772

Related: odoo/upgrade#772
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Odoo's Mergebot
2020-02-19 13:10:08 +01:00
committed by GitHub
7 changed files with 43 additions and 42 deletions
+10
View File
@@ -158,3 +158,13 @@ class LivechatController(http.Controller):
('uuid', '=', uuid)], limit=1)
if channel:
channel._email_livechat_transcript(email)
@http.route('/im_livechat/visitor_leave_session', type='json', auth="public")
def visitor_leave_session(self, uuid):
""" Called when the livechat visitor leaves the conversation.
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()
@@ -123,6 +123,7 @@ class ImLivechatChannel(models.Model):
channel_partner_to_add.append((4, visitor_user.partner_id.id))
return {
'channel_partner_ids': channel_partner_to_add,
'livechat_active': True,
'livechat_operator_id': operator_partner_id,
'livechat_channel_id': self.id,
'anonymous_name': False if user_id else anonymous_name,
+16
View File
@@ -33,6 +33,7 @@ class MailChannel(models.Model):
anonymous_name = fields.Char('Anonymous Name')
channel_type = fields.Selection(selection_add=[('livechat', 'Livechat Conversation')])
livechat_active = fields.Boolean('Is livechat ongoing?', help='Livechat session is active until visitor leave the conversation.')
livechat_channel_id = fields.Many2one('im_livechat.channel', 'Channel')
livechat_operator_id = fields.Many2one('res.partner', string='Operator', help="""Operator for this specific channel""")
country_id = fields.Many2one('res.country', string="Country", help="Country of the visitor of the channel")
@@ -157,6 +158,21 @@ class MailChannel(models.Model):
'info': 'transient_message',
})
def _get_visitor_leave_message(self, operator=False, cancel=False):
return _('Visitor has left the conversation.')
def _close_livechat_session(self, **kwargs):
""" Set deactivate the livechat channel and notify (the operator) the reason of closing the session."""
self.ensure_one()
if self.livechat_active:
self.livechat_active = False
# avoid useless notification if the channel is empty
if not self.channel_message_ids:
return
# Notify that the visitor has left the conversation
self.message_post(author_id=self.env.ref('base.partner_root').id,
body=self._get_visitor_leave_message(**kwargs), message_type='comment', subtype_xmlid='mail.mt_comment')
# Rating Mixin
def _rating_get_parent_field_name(self):
@@ -65,16 +65,6 @@ class WebsiteLivechat(LivechatController):
anonymous_name = visitor_sudo.display_name
return super(WebsiteLivechat, self).get_session(channel_id, anonymous_name, previous_operator_id=previous_operator_id, **kwargs)
@http.route('/im_livechat/visitor_leave_session', type='json', auth="public")
def visitor_leave_session(self, uuid):
""" Called when the livechat visitor leaves the conversation.
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_request_session()
@http.route('/im_livechat/close_empty_livechat', type='json', auth="public")
def close_empty_livechat(self, uuid):
""" Called when an operator send a chat request to a visitor but does not speak to him and closes
@@ -11,15 +11,12 @@ class ImLivechatChannel(models.Model):
mail_channel_vals = super(ImLivechatChannel, self)._get_livechat_mail_channel_vals(anonymous_name, operator, user_id=user_id, country_id=country_id)
visitor_sudo = self.env['website.visitor']._get_visitor_from_request()
if visitor_sudo:
mail_channel_vals.update({
'livechat_visitor_id': visitor_sudo.id,
'livechat_active': True
})
mail_channel_vals['livechat_visitor_id'] = visitor_sudo.id
if not user_id:
mail_channel_vals['anonymous_name'] = visitor_sudo.display_name + (' (%s)' % visitor_sudo.country_id.name if visitor_sudo.country_id else '')
# As chat requested by the visitor, delete the chat requested by an operator if any to avoid conflicts between two flows
chat_request_channel = self.env['mail.channel'].sudo().search([('livechat_visitor_id', '=', visitor_sudo.id), ('livechat_active', '=', True)])
for mail_channel in chat_request_channel:
mail_channel.close_livechat_request_session(type='cancel', speaking_with=operator.name)
mail_channel._close_livechat_session(cancel=True, speaking_with=operator.name)
return mail_channel_vals
+9 -18
View File
@@ -8,7 +8,6 @@ class MailChannel(models.Model):
_inherit = 'mail.channel'
livechat_visitor_id = fields.Many2one('website.visitor', string='Visitor')
livechat_active = fields.Boolean('Is livechat ongoing?', help='Livechat session is not considered as active if the visitor left the conversation.')
def _execute_channel_pin(self, pinned=False):
""" Override to clean an empty livechat channel.
@@ -53,23 +52,15 @@ class MailChannel(models.Model):
recent_history = self.env['website.track'].search([('page_id', '!=', False), ('visitor_id', '=', visitor.id)], limit=3)
return ' → '.join(visit.page_id.name + ' (' + visit.visit_datetime.strftime('%H:%M') + ')' for visit in reversed(recent_history))
def close_livechat_request_session(self, type='leave', **kwargs):
""" Set deactivate the livechat channel and notify (the operator) the reason of closing the session."""
self.ensure_one()
if self.livechat_active:
self.livechat_active = False
# avoid useless notification if the channel is empty
if not self.channel_message_ids:
return
# Notify that the visitor has left the conversation
name = _('The visitor') if not self.livechat_visitor_id else self.livechat_visitor_id.display_name
if type == 'cancel':
message = _('has started a conversation with %s. The chat request has been canceled.') % kwargs.get('speaking_with', 'an operator')
else:
message = _('has left the conversation.')
leave_message = '%s %s' % (name, message)
self.message_post(author_id=self.env.ref('base.user_root').sudo().partner_id.id,
body=leave_message, message_type='comment', subtype_xmlid='mail.mt_comment')
def _get_visitor_leave_message(self, operator=False, cancel=False):
name = _('The visitor') if not self.livechat_visitor_id else self.livechat_visitor_id.display_name
if cancel:
message = _("""%s has started a conversation with %s.
The chat request has been canceled.""") % (name, operator or _('an operator'))
else:
message = _('%s has left the conversation.') % name
return message
def message_post(self, **kwargs):
"""Override to mark the visitor as still connected.
@@ -25,21 +25,17 @@ LivechatButton.include({
/**
* @override
* Called when the visitor closes the livechat chatter
* (no matter the way : close, send feedback, ..)
* Called when the visitor closes the livechat chatter the first time (first click on X button)
* this will deactivate the mail_channel, clean the chat request if any
* and allow the operators to send the visitor a new chat request
*/
_closeChat: function () {
var self = this;
_onCloseChatWindow: function (ev) {
this._super(ev);
var cookie = utils.get_cookie('im_livechat_session');
if (cookie) {
var channel = JSON.parse(cookie);
var ready = session.rpc('/im_livechat/visitor_leave_session', {uuid: channel.uuid});
ready.then(self._super());
}
else {
this._super();
session.rpc('/im_livechat/visitor_leave_session', {uuid: channel.uuid});
utils.set_cookie('im_livechat_session', "", -1); // remove cookie
}
},
});