[MIG] im_chat, im_livechat : re structure the modules files.
Create models/ and controllers/ directories, and split the Python and XML files to fit coding guidelines, and prepare migration.
This commit is contained in:
@@ -1 +1,3 @@
|
||||
import bus
|
||||
# -*- coding: utf-8 -*-
|
||||
import models
|
||||
import controllers
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import main
|
||||
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import openerp
|
||||
from openerp.http import request
|
||||
|
||||
from openerp.addons.bus.models.bus import dispatch
|
||||
|
||||
|
||||
class BusController(openerp.http.Controller):
|
||||
""" Examples:
|
||||
openerp.jsonRpc('/longpolling/poll','call',{"channels":["c1"],last:0}).then(function(r){console.log(r)});
|
||||
openerp.jsonRpc('/longpolling/send','call',{"channel":"c1","message":"m1"});
|
||||
openerp.jsonRpc('/longpolling/send','call',{"channel":"c2","message":"m2"});
|
||||
"""
|
||||
|
||||
@openerp.http.route('/longpolling/send', type="json", auth="public")
|
||||
def send(self, channel, message):
|
||||
if not isinstance(channel, basestring):
|
||||
raise Exception("bus.Bus only string channels are allowed.")
|
||||
registry, cr, uid = request.registry, request.cr, request.session.uid
|
||||
return registry['bus.bus'].sendone(cr, uid, channel, message)
|
||||
|
||||
# override to add channels
|
||||
def _poll(self, dbname, channels, last, options):
|
||||
request.cr.close()
|
||||
request._cr = None
|
||||
return dispatch.poll(dbname, channels, last)
|
||||
|
||||
@openerp.http.route('/longpolling/poll', type="json", auth="public")
|
||||
def poll(self, channels, last, options=None):
|
||||
if options is None:
|
||||
options = {}
|
||||
if not dispatch:
|
||||
raise Exception("bus.Bus unavailable")
|
||||
if [c for c in channels if not isinstance(c, basestring)]:
|
||||
raise Exception("bus.Bus only string channels are allowed.")
|
||||
return self._poll(request.db, channels, last, options)
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import bus
|
||||
@@ -156,37 +156,3 @@ class ImDispatch(object):
|
||||
return self
|
||||
|
||||
dispatch = ImDispatch().start()
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Controller
|
||||
#----------------------------------------------------------
|
||||
class Controller(openerp.http.Controller):
|
||||
""" Examples:
|
||||
openerp.jsonRpc('/longpolling/poll','call',{"channels":["c1"],last:0}).then(function(r){console.log(r)});
|
||||
openerp.jsonRpc('/longpolling/send','call',{"channel":"c1","message":"m1"});
|
||||
openerp.jsonRpc('/longpolling/send','call',{"channel":"c2","message":"m2"});
|
||||
"""
|
||||
|
||||
@openerp.http.route('/longpolling/send', type="json", auth="public")
|
||||
def send(self, channel, message):
|
||||
if not isinstance(channel, basestring):
|
||||
raise Exception("bus.Bus only string channels are allowed.")
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
return registry['bus.bus'].sendone(cr, uid, channel, message)
|
||||
|
||||
# override to add channels
|
||||
def _poll(self, dbname, channels, last, options):
|
||||
request.cr.close()
|
||||
request._cr = None
|
||||
return dispatch.poll(dbname, channels, last)
|
||||
|
||||
@openerp.http.route('/longpolling/poll', type="json", auth="public")
|
||||
def poll(self, channels, last, options=None):
|
||||
if options is None:
|
||||
options = {}
|
||||
if not dispatch:
|
||||
raise Exception("bus.Bus unavailable")
|
||||
if [c for c in channels if not isinstance(c, basestring)]:
|
||||
print channels
|
||||
raise Exception("bus.Bus only string channels are allowed.")
|
||||
return self._poll(request.db, channels, last, options)
|
||||
@@ -1 +1,3 @@
|
||||
import im_chat
|
||||
# -*- coding: utf-8 -*-
|
||||
import models
|
||||
import controllers
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name' : 'Instant Messaging',
|
||||
'version': '1.0',
|
||||
'summary': 'OpenERP Chat',
|
||||
'author': 'OpenERP SA',
|
||||
'summary': 'Chat between users',
|
||||
'author': 'Odoo SA',
|
||||
'sequence': '18',
|
||||
'category': 'Tools',
|
||||
'complexity': 'easy',
|
||||
@@ -11,18 +12,17 @@
|
||||
"""
|
||||
Instant Messaging
|
||||
=================
|
||||
|
||||
Allows users to chat with each other in real time. Find other users easily and
|
||||
chat in real time. It support several chats in parallel.
|
||||
""",
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/im_security.xml',
|
||||
'views/im_chat.xml',
|
||||
'views/im_chat_view.xml',
|
||||
'im_chat_data.xml',
|
||||
],
|
||||
'depends' : ['base', 'web', 'bus'],
|
||||
'security/im_chat_session_security.xml',
|
||||
'views/im_chat_session_templates.xml',
|
||||
'views/im_chat_session_views.xml',
|
||||
'data/im_chat_session_data.xml',
|
||||
],
|
||||
'depends': ['base', 'web', 'bus'],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'application': True,
|
||||
'installable': True,
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*
|
||||
import main
|
||||
@@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*
|
||||
import base64
|
||||
import openerp
|
||||
import simplejson
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.http import request
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Controllers
|
||||
#----------------------------------------------------------
|
||||
class Controller(openerp.addons.bus.controllers.main.BusController):
|
||||
def _poll(self, dbname, channels, last, options):
|
||||
if request.session.uid:
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
registry.get('im_chat.presence').update(cr, uid, options.get('im_presence', False), context=context)
|
||||
## For performance issue, the real time status notification is disabled. This means a change of status are still braoadcasted
|
||||
## but not received by anyone. Otherwise, all listening user restart their longpolling at the same time and cause a 'ConnectionPool Full Error'
|
||||
## since there is not enought cursors for everyone. Now, when a user open his list of users, an RPC call is made to update his user status list.
|
||||
##channels.append((request.db,'im_chat.presence'))
|
||||
# channel to receive message
|
||||
channels.append((request.db,'im_chat.session', request.uid))
|
||||
return super(Controller, self)._poll(dbname, channels, last, options)
|
||||
|
||||
@openerp.http.route('/im_chat/init', type="json", auth="none")
|
||||
def init(self):
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
notifications = registry['im_chat.message'].init_messages(cr, uid, context=context)
|
||||
return notifications
|
||||
|
||||
@openerp.http.route('/im_chat/post', type="json", auth="none")
|
||||
def post(self, uuid, message_type, message_content):
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
# execute the post method as SUPERUSER_ID
|
||||
message_id = registry["im_chat.message"].post(cr, openerp.SUPERUSER_ID, uid, uuid, message_type, message_content, context=context)
|
||||
return message_id
|
||||
|
||||
@openerp.http.route(['/im_chat/image/<string:uuid>/<string:user_id>'], type='http', auth="none")
|
||||
def image(self, uuid, user_id):
|
||||
registry, cr, context, uid = request.registry, request.cr, request.context, request.session.uid
|
||||
# get the image
|
||||
Session = registry.get("im_chat.session")
|
||||
image_b64 = Session.get_image(cr, openerp.SUPERUSER_ID, uuid, simplejson.loads(user_id), context)
|
||||
# built the response
|
||||
image_data = base64.b64decode(image_b64)
|
||||
headers = [('Content-Type', 'image/png')]
|
||||
headers.append(('Content-Length', len(image_data)))
|
||||
return request.make_response(image_data, headers)
|
||||
|
||||
@openerp.http.route(['/im_chat/history'], type="json", auth="none")
|
||||
def history(self, uuid, last_id=False, limit=20):
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid or openerp.SUPERUSER_ID, request.context
|
||||
return registry["im_chat.message"].get_messages(cr, uid, uuid, last_id, limit, context=context)
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import im_chat_session
|
||||
import res_users
|
||||
@@ -6,7 +6,6 @@ import time
|
||||
import uuid
|
||||
import random
|
||||
import re
|
||||
import simplejson
|
||||
import openerp
|
||||
import cgi
|
||||
|
||||
@@ -14,7 +13,7 @@ from openerp import tools, _
|
||||
from openerp.http import request
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.addons.bus.bus import TIMEOUT
|
||||
from openerp.addons.bus.models.bus import TIMEOUT
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -394,119 +393,3 @@ class im_chat_presence(osv.Model):
|
||||
notifications.append([(cr.dbname,'im_chat.presence'), {'id': presence.user_id.id, 'im_status': presence.status}])
|
||||
self.pool['bus.bus'].sendmany(cr, uid, notifications)
|
||||
return True
|
||||
|
||||
class res_users(osv.Model):
|
||||
_inherit = "res.users"
|
||||
|
||||
def _get_im_status(self, cr, uid, ids, fields, arg, context=None):
|
||||
""" function computing the im_status field of the users """
|
||||
r = dict((i, 'offline') for i in ids)
|
||||
status_ids = self.pool['im_chat.presence'].search(cr, uid, [('user_id', 'in', ids)], context=context)
|
||||
status = self.pool['im_chat.presence'].browse(cr, uid, status_ids, context=context)
|
||||
for s in status:
|
||||
r[s.user_id.id] = s.status
|
||||
return r
|
||||
|
||||
_columns = {
|
||||
'im_status' : fields.function(_get_im_status, type="char", string="IM Status"),
|
||||
}
|
||||
|
||||
def im_search(self, cr, uid, name, limit=20, context=None):
|
||||
""" search users with a name and return its id, name and im_status """
|
||||
result = [];
|
||||
# find the employee group
|
||||
group_employee = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')[1]
|
||||
|
||||
where_clause_base = " U.active = 't' "
|
||||
query_params = ()
|
||||
if name:
|
||||
where_clause_base += " AND P.name ILIKE %s "
|
||||
query_params = query_params + ('%'+name+'%',)
|
||||
|
||||
# first query to find online employee
|
||||
cr.execute('''SELECT U.id as id, P.name as name, COALESCE(S.status, 'offline') as im_status
|
||||
FROM im_chat_presence S
|
||||
JOIN res_users U ON S.user_id = U.id
|
||||
JOIN res_partner P ON P.id = U.partner_id
|
||||
WHERE '''+where_clause_base+'''
|
||||
AND U.id != %s
|
||||
AND EXISTS (SELECT 1 FROM res_groups_users_rel G WHERE G.gid = %s AND G.uid = U.id)
|
||||
AND S.status = 'online'
|
||||
ORDER BY P.name
|
||||
LIMIT %s
|
||||
''', query_params + (uid, group_employee, limit))
|
||||
result = result + cr.dictfetchall()
|
||||
|
||||
# second query to find other online people
|
||||
if(len(result) < limit):
|
||||
cr.execute('''SELECT U.id as id, P.name as name, COALESCE(S.status, 'offline') as im_status
|
||||
FROM im_chat_presence S
|
||||
JOIN res_users U ON S.user_id = U.id
|
||||
JOIN res_partner P ON P.id = U.partner_id
|
||||
WHERE '''+where_clause_base+'''
|
||||
AND U.id NOT IN %s
|
||||
AND S.status = 'online'
|
||||
ORDER BY P.name
|
||||
LIMIT %s
|
||||
''', query_params + (tuple([u["id"] for u in result]) + (uid,), limit-len(result)))
|
||||
result = result + cr.dictfetchall()
|
||||
|
||||
# third query to find all other people
|
||||
if(len(result) < limit):
|
||||
cr.execute('''SELECT U.id as id, P.name as name, COALESCE(S.status, 'offline') as im_status
|
||||
FROM res_users U
|
||||
LEFT JOIN im_chat_presence S ON S.user_id = U.id
|
||||
LEFT JOIN res_partner P ON P.id = U.partner_id
|
||||
WHERE '''+where_clause_base+'''
|
||||
AND U.id NOT IN %s
|
||||
ORDER BY P.name
|
||||
LIMIT %s
|
||||
''', query_params + (tuple([u["id"] for u in result]) + (uid,), limit-len(result)))
|
||||
result = result + cr.dictfetchall()
|
||||
return result
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Controllers
|
||||
#----------------------------------------------------------
|
||||
class Controller(openerp.addons.bus.bus.Controller):
|
||||
def _poll(self, dbname, channels, last, options):
|
||||
if request.session.uid:
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
registry.get('im_chat.presence').update(cr, uid, options.get('im_presence', False), context=context)
|
||||
## For performance issue, the real time status notification is disabled. This means a change of status are still braoadcasted
|
||||
## but not received by anyone. Otherwise, all listening user restart their longpolling at the same time and cause a 'ConnectionPool Full Error'
|
||||
## since there is not enought cursors for everyone. Now, when a user open his list of users, an RPC call is made to update his user status list.
|
||||
##channels.append((request.db,'im_chat.presence'))
|
||||
# channel to receive message
|
||||
channels.append((request.db,'im_chat.session', request.uid))
|
||||
return super(Controller, self)._poll(dbname, channels, last, options)
|
||||
|
||||
@openerp.http.route('/im_chat/init', type="json", auth="none")
|
||||
def init(self):
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
notifications = registry['im_chat.message'].init_messages(cr, uid, context=context)
|
||||
return notifications
|
||||
|
||||
@openerp.http.route('/im_chat/post', type="json", auth="none")
|
||||
def post(self, uuid, message_type, message_content):
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid, request.context
|
||||
# execute the post method as SUPERUSER_ID
|
||||
message_id = registry["im_chat.message"].post(cr, openerp.SUPERUSER_ID, uid, uuid, message_type, message_content, context=context)
|
||||
return message_id
|
||||
|
||||
@openerp.http.route(['/im_chat/image/<string:uuid>/<string:user_id>'], type='http', auth="none")
|
||||
def image(self, uuid, user_id):
|
||||
registry, cr, context, uid = request.registry, request.cr, request.context, request.session.uid
|
||||
# get the image
|
||||
Session = registry.get("im_chat.session")
|
||||
image_b64 = Session.get_image(cr, openerp.SUPERUSER_ID, uuid, simplejson.loads(user_id), context)
|
||||
# built the response
|
||||
image_data = base64.b64decode(image_b64)
|
||||
headers = [('Content-Type', 'image/png')]
|
||||
headers.append(('Content-Length', len(image_data)))
|
||||
return request.make_response(image_data, headers)
|
||||
|
||||
@openerp.http.route(['/im_chat/history'], type="json", auth="none")
|
||||
def history(self, uuid, last_id=False, limit=20):
|
||||
registry, cr, uid, context = request.registry, request.cr, request.session.uid or openerp.SUPERUSER_ID, request.context
|
||||
return registry["im_chat.message"].get_messages(cr, uid, uuid, last_id, limit, context=context)
|
||||
@@ -0,0 +1,75 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
|
||||
|
||||
class res_users(osv.osv):
|
||||
_inherit = "res.users"
|
||||
|
||||
def _get_im_status(self, cr, uid, ids, fields, arg, context=None):
|
||||
""" function computing the im_status field of the users """
|
||||
r = dict((i, 'offline') for i in ids)
|
||||
status_ids = self.pool['im_chat.presence'].search(cr, uid, [('user_id', 'in', ids)], context=context)
|
||||
status = self.pool['im_chat.presence'].browse(cr, uid, status_ids, context=context)
|
||||
for s in status:
|
||||
r[s.user_id.id] = s.status
|
||||
return r
|
||||
|
||||
_columns = {
|
||||
'im_status' : fields.function(_get_im_status, type="char", string="IM Status"),
|
||||
}
|
||||
|
||||
def im_search(self, cr, uid, name, limit=20, context=None):
|
||||
""" search users with a name and return its id, name and im_status """
|
||||
result = [];
|
||||
# find the employee group
|
||||
group_employee = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')[1]
|
||||
|
||||
where_clause_base = " U.active = 't' "
|
||||
query_params = ()
|
||||
if name:
|
||||
where_clause_base += " AND P.name ILIKE %s "
|
||||
query_params = query_params + ('%'+name+'%',)
|
||||
|
||||
# first query to find online employee
|
||||
cr.execute('''SELECT U.id as id, P.name as name, COALESCE(S.status, 'offline') as im_status
|
||||
FROM im_chat_presence S
|
||||
JOIN res_users U ON S.user_id = U.id
|
||||
JOIN res_partner P ON P.id = U.partner_id
|
||||
WHERE '''+where_clause_base+'''
|
||||
AND U.id != %s
|
||||
AND EXISTS (SELECT 1 FROM res_groups_users_rel G WHERE G.gid = %s AND G.uid = U.id)
|
||||
AND S.status = 'online'
|
||||
ORDER BY P.name
|
||||
LIMIT %s
|
||||
''', query_params + (uid, group_employee, limit))
|
||||
result = result + cr.dictfetchall()
|
||||
|
||||
# second query to find other online people
|
||||
if(len(result) < limit):
|
||||
cr.execute('''SELECT U.id as id, P.name as name, COALESCE(S.status, 'offline') as im_status
|
||||
FROM im_chat_presence S
|
||||
JOIN res_users U ON S.user_id = U.id
|
||||
JOIN res_partner P ON P.id = U.partner_id
|
||||
WHERE '''+where_clause_base+'''
|
||||
AND U.id NOT IN %s
|
||||
AND S.status = 'online'
|
||||
ORDER BY P.name
|
||||
LIMIT %s
|
||||
''', query_params + (tuple([u["id"] for u in result]) + (uid,), limit-len(result)))
|
||||
result = result + cr.dictfetchall()
|
||||
|
||||
# third query to find all other people
|
||||
if(len(result) < limit):
|
||||
cr.execute('''SELECT U.id as id, P.name as name, COALESCE(S.status, 'offline') as im_status
|
||||
FROM res_users U
|
||||
LEFT JOIN im_chat_presence S ON S.user_id = U.id
|
||||
LEFT JOIN res_partner P ON P.id = U.partner_id
|
||||
WHERE '''+where_clause_base+'''
|
||||
AND U.id NOT IN %s
|
||||
ORDER BY P.name
|
||||
LIMIT %s
|
||||
''', query_params + (tuple([u["id"] for u in result]) + (uid,), limit-len(result)))
|
||||
result = result + cr.dictfetchall()
|
||||
return result
|
||||
+3
-3
@@ -4,10 +4,10 @@
|
||||
<data>
|
||||
<template id="assets_backend" name="im_chat assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/im_chat/static/src/css/im_common.css"/>
|
||||
<link rel="stylesheet" href="/im_chat/static/src/css/im_chat.css"/>
|
||||
<link rel="stylesheet" href="/im_chat/static/src/css/im_chat_common.css"/>
|
||||
<link rel="stylesheet" href="/im_chat/static/src/css/im_chat_backend.css"/>
|
||||
<script type="text/javascript" src="/im_chat/static/src/js/im_chat_common.js"></script>
|
||||
<script type="text/javascript" src="/im_chat/static/src/js/im_chat.js"></script>
|
||||
<script type="text/javascript" src="/im_chat/static/src/js/im_chat_backend.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import controllers
|
||||
import im_livechat
|
||||
import report
|
||||
import models
|
||||
import report
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name' : 'Live Chat',
|
||||
'author': 'OpenERP SA',
|
||||
'author': 'Odoo SA',
|
||||
'version': '1.0',
|
||||
'summary': 'Live Chat with Visitors/Customers',
|
||||
'category': 'Tools',
|
||||
@@ -18,15 +19,16 @@ Help your customers with this chat, and analyse their feedback.
|
||||
|
||||
""",
|
||||
'data': [
|
||||
"security/im_livechat_security.xml",
|
||||
"security/im_livechat_channel_security.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"views/im_livechat_view.xml",
|
||||
"views/im_livechat.xml",
|
||||
"report/im_livechat_report.xml",
|
||||
"im_livechat_data.xml"
|
||||
"views/im_chat_session_views.xml",
|
||||
"views/im_livechat_channel_views.xml",
|
||||
"views/im_livechat_channel_templates.xml",
|
||||
"report/im_livechat_report_views.xml",
|
||||
"data/im_livechat_channel_data.xml"
|
||||
],
|
||||
'demo': [
|
||||
"im_livechat_demo.xml",
|
||||
"data/im_livechat_channel_demo.xml",
|
||||
],
|
||||
'depends' : ["mail", "rating", "im_chat"],
|
||||
'installable': True,
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import livechat
|
||||
import rating
|
||||
import main
|
||||
|
||||
@@ -67,3 +67,35 @@ class LivechatController(http.Controller):
|
||||
with reg.cursor() as cr:
|
||||
return len(reg.get('im_livechat.channel').get_available_users(cr, uid, channel)) > 0
|
||||
|
||||
@http.route('/rating/livechat/feedback', type='json', auth='none')
|
||||
def rating_livechat_feedback(self, uuid, rate, reason=None, **kwargs):
|
||||
Session = request.env['im_chat.session']
|
||||
Rating = request.env['rating.rating']
|
||||
session_ids = Session.sudo().search([('uuid', '=', uuid)])
|
||||
if session_ids:
|
||||
session = session_ids[0]
|
||||
# limit the creation : only ONE rating per session
|
||||
values = {
|
||||
'rating' : rate,
|
||||
}
|
||||
if not session.rating_ids:
|
||||
values.update({
|
||||
'res_id' : session.id,
|
||||
'res_model' : 'im_chat.session',
|
||||
'rating' : rate,
|
||||
'feedback' : reason,
|
||||
})
|
||||
# find the partner related to the user of the conversation
|
||||
rated_partner_id = False
|
||||
if session.user_ids:
|
||||
rated_partner_id = session.user_ids[0] and session.user_ids[0].partner_id.id or False
|
||||
values['rated_partner_id'] = rated_partner_id
|
||||
# create the rating
|
||||
rating = Rating.sudo().create(values)
|
||||
else:
|
||||
if reason:
|
||||
values['feedback'] = reason
|
||||
rating = session.rating_ids[0]
|
||||
rating.write(values)
|
||||
return rating.id
|
||||
return False
|
||||
@@ -1,40 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import openerp
|
||||
from openerp.addons.rating.controllers.main import Rating
|
||||
from openerp.addons.web import http
|
||||
from openerp.http import request
|
||||
|
||||
class LivechatRatingController(Rating):
|
||||
|
||||
@http.route('/rating/livechat/feedback', type='json', auth='none')
|
||||
def rating_livechat_feedback(self, uuid, rate, reason=None, **kwargs):
|
||||
Session = request.env['im_chat.session']
|
||||
Rating = request.env['rating.rating']
|
||||
session_ids = Session.sudo().search([('uuid', '=', uuid)])
|
||||
if session_ids:
|
||||
session = session_ids[0]
|
||||
# limit the creation : only ONE rating per session
|
||||
values = {
|
||||
'rating' : rate,
|
||||
}
|
||||
if not session.rating_ids:
|
||||
values.update({
|
||||
'res_id' : session.id,
|
||||
'res_model' : 'im_chat.session',
|
||||
'rating' : rate,
|
||||
'feedback' : reason,
|
||||
})
|
||||
# find the partner related to the user of the conversation
|
||||
rated_partner_id = False
|
||||
if session.user_ids:
|
||||
rated_partner_id = session.user_ids[0] and session.user_ids[0].partner_id.id or False
|
||||
values['rated_partner_id'] = rated_partner_id
|
||||
# create the rating
|
||||
rating = Rating.sudo().create(values)
|
||||
else:
|
||||
if reason:
|
||||
values['feedback'] = reason
|
||||
rating = session.rating_ids[0]
|
||||
rating.write(values)
|
||||
return rating.id
|
||||
return False
|
||||
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*
|
||||
import im_livechat_channel
|
||||
import im_chat_session
|
||||
import rating
|
||||
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import openerp
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
|
||||
class im_chat_session(osv.Model):
|
||||
|
||||
_name = 'im_chat.session'
|
||||
_inherit = ['im_chat.session', 'rating.mixin']
|
||||
|
||||
def _get_fullname(self, cr, uid, ids, fields, arg, context=None):
|
||||
""" built the complete name of the session """
|
||||
result = {}
|
||||
sessions = self.browse(cr, uid, ids, context=context)
|
||||
for session in sessions:
|
||||
names = []
|
||||
for user in session.user_ids:
|
||||
names.append(user.name)
|
||||
if session.anonymous_name:
|
||||
names.append(session.anonymous_name)
|
||||
result[session.id] = ', '.join(names)
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'anonymous_name' : fields.char('Anonymous Name'),
|
||||
'create_date': fields.datetime('Create Date', required=True, select=True),
|
||||
'channel_id': fields.many2one("im_livechat.channel", "Channel"),
|
||||
'fullname': fields.function(_get_fullname, type="char", string="Complete name"),
|
||||
}
|
||||
|
||||
def is_in_session(self, cr, uid, uuid, user_id, context=None):
|
||||
""" return if the given user_id is in the session """
|
||||
sids = self.search(cr, uid, [('uuid', '=', uuid)], context=context, limit=1)
|
||||
for session in self.browse(cr, uid, sids, context=context):
|
||||
if session.anonymous_name and user_id == openerp.SUPERUSER_ID:
|
||||
return True
|
||||
else:
|
||||
return super(im_chat_session, self).is_in_session(cr, uid, uuid, user_id, context=context)
|
||||
return False
|
||||
|
||||
def users_infos(self, cr, uid, ids, context=None):
|
||||
""" add the anonymous user in the user of the session """
|
||||
for session in self.browse(cr, uid, ids, context=context):
|
||||
users_infos = super(im_chat_session, self).users_infos(cr, uid, ids, context=context)
|
||||
if session.anonymous_name:
|
||||
users_infos.append({'id' : False, 'name' : session.anonymous_name, 'im_status' : 'online'})
|
||||
return users_infos
|
||||
|
||||
def quit_user(self, cr, uid, uuid, context=None):
|
||||
""" action of leaving a given session """
|
||||
sids = self.search(cr, uid, [('uuid', '=', uuid)], context=context, limit=1)
|
||||
for session in self.browse(cr, openerp.SUPERUSER_ID, sids, context=context):
|
||||
if session.anonymous_name:
|
||||
# an identified user can leave an anonymous session if there is still another idenfied user in it
|
||||
if uid and uid in [u.id for u in session.user_ids] and len(session.user_ids) > 1:
|
||||
self.remove_user(cr, uid, session.id, context=context)
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
return super(im_chat_session, self).quit_user(cr, uid, session.id, context=context)
|
||||
|
||||
|
||||
def cron_remove_empty_session(self, cr, uid, context=None):
|
||||
groups = self.pool['im_chat.message'].read_group(cr, uid, [], ['to_id'], ['to_id'], context=context)
|
||||
not_empty_session_ids = [group['to_id'][0] for group in groups]
|
||||
empty_session_ids = self.search(cr, uid, [('id', 'not in', not_empty_session_ids), ('channel_id', '!=', False)], context=context)
|
||||
self.unlink(cr, uid, empty_session_ids, context=context)
|
||||
@@ -1,24 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import openerp
|
||||
import openerp.addons.im_chat.im_chat
|
||||
import random
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from openerp import api, models
|
||||
|
||||
|
||||
class Rating(models.Model):
|
||||
|
||||
_inherit = "rating.rating"
|
||||
|
||||
@api.one
|
||||
@api.depends('res_model', 'res_id')
|
||||
def _compute_res_name(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 self.res_model == 'im_chat.session':
|
||||
current_object = self.env[self.res_model].sudo().browse(self.res_id)
|
||||
self.res_name = ('%s / %s') % (current_object.channel_id.name, current_object.id)
|
||||
else:
|
||||
super(Rating, self)._compute_res_name()
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- History : form, list and search views -->
|
||||
<record id="action_session_history" model="ir.actions.act_window">
|
||||
<field name="name">History</field>
|
||||
<field name="res_model">im_chat.session</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('channel_id', '!=', None)]</field>
|
||||
<field name="context">{'group_by': ['channel_id', 'create_date:month']}</field>
|
||||
</record>
|
||||
|
||||
<record id="im_chat_session_search" model="ir.ui.view">
|
||||
<field name="name">im_chat.session.search</field>
|
||||
<field name="model">im_chat.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search history">
|
||||
<filter name="id" string="My sessions" domain="[('user_ids','in', uid)]"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter name="group_by_channel" string="Channel" domain="[]" context="{'group_by':'channel_id'}"/>
|
||||
<separator orientation="vertical" />
|
||||
<filter name="group_by_day" string="Creation date (day)" domain="[]" context="{'group_by':'create_date:day'}"/>
|
||||
<filter name="group_by_week" string="Creation date (week)" domain="[]" context="{'group_by':'create_date:week'}"/>
|
||||
<filter name="group_by_month" string="Creation date (month)" domain="[]" context="{'group_by':'create_date:month'}" />
|
||||
<filter name="group_by_year" string="Creation date (year)" domain="[]" context="{'group_by':'create_date:year'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="im_chat_session_list_view" model="ir.ui.view">
|
||||
<field name="name">im_chat.session.tree</field>
|
||||
<field name="model">im_chat.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="History" create="false">
|
||||
<field name="id"/>
|
||||
<field name="fullname"/>
|
||||
<field name="create_date"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="im_chat_session_form_view" model="ir.ui.view">
|
||||
<field name="name">im_chat.session.form</field>
|
||||
<field name="model">im_chat.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Session Form" create="false" edit="false">
|
||||
<sheet>
|
||||
<group>
|
||||
<group string="General">
|
||||
<field name="id"/>
|
||||
<field name="fullname" />
|
||||
<field name="create_date" readonly="1"/>
|
||||
</group>
|
||||
<group string="Feedback">
|
||||
<field name="rating_ids" mode="kanban" nolabel="1">
|
||||
<kanban>
|
||||
<field name="rating"/>
|
||||
<field name="feedback"/>
|
||||
<field name="res_name"/>
|
||||
<field name="create_date"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_group_details" style="min-height: 40px">
|
||||
<img t-attf-src="rating/static/src/img/rating_#{record.rating.raw_value and record.rating.raw_value or 0}.png" class="oe_kanban_image" style="float:left; margin-right: 10px;"/>
|
||||
<span t-if="record.feedback.raw_value">
|
||||
<t t-esc="record.feedback.raw_value"/>
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</group>
|
||||
</group>
|
||||
<field name="message_ids" type="tree">
|
||||
<tree string="History">
|
||||
<field name="create_date" />
|
||||
<field name="from_id" />
|
||||
<field name="message" />
|
||||
</tree>
|
||||
</field>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
+1
-1
@@ -139,7 +139,7 @@
|
||||
<script type="text/javascript" src="/im_chat/static/src/js/im_chat_common.js"></script>
|
||||
<script type="text/javascript" src="/im_livechat/static/src/js/im_livechat.js"></script>
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="/im_chat/static/src/css/im_common.css"></link>
|
||||
<link rel="stylesheet" href="/im_chat/static/src/css/im_chat_common.css"></link>
|
||||
<link rel="stylesheet" href="/im_livechat/static/src/css/im_livechat.css"/>
|
||||
</template>
|
||||
|
||||
-102
@@ -1,108 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!--
|
||||
Views for im_chat.session
|
||||
-->
|
||||
<!-- History : form, list and search views -->
|
||||
<record id="action_session_history" model="ir.actions.act_window">
|
||||
<field name="name">History</field>
|
||||
<field name="res_model">im_chat.session</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('channel_id', '!=', None)]</field>
|
||||
<field name="context">{'group_by': ['channel_id', 'create_date:month']}</field>
|
||||
</record>
|
||||
|
||||
<record id="im_chat_session_search" model="ir.ui.view">
|
||||
<field name="name">im_chat.session.search</field>
|
||||
<field name="model">im_chat.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search history">
|
||||
<filter name="id" string="My sessions" domain="[('user_ids','in', uid)]"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter name="group_by_channel" string="Channel" domain="[]" context="{'group_by':'channel_id'}"/>
|
||||
<separator orientation="vertical" />
|
||||
<filter name="group_by_day" string="Creation date (day)" domain="[]" context="{'group_by':'create_date:day'}"/>
|
||||
<filter name="group_by_week" string="Creation date (week)" domain="[]" context="{'group_by':'create_date:week'}"/>
|
||||
<filter name="group_by_month" string="Creation date (month)" domain="[]" context="{'group_by':'create_date:month'}" />
|
||||
<filter name="group_by_year" string="Creation date (year)" domain="[]" context="{'group_by':'create_date:year'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="im_chat_session_list_view" model="ir.ui.view">
|
||||
<field name="name">im_chat.session.tree</field>
|
||||
<field name="model">im_chat.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="History" create="false">
|
||||
<field name="id"/>
|
||||
<field name="fullname"/>
|
||||
<field name="create_date"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="im_chat_session_form_view" model="ir.ui.view">
|
||||
<field name="name">im_chat.session.form</field>
|
||||
<field name="model">im_chat.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Session Form" create="false" edit="false">
|
||||
<sheet>
|
||||
<group>
|
||||
<group string="General">
|
||||
<field name="id"/>
|
||||
<field name="fullname" />
|
||||
<field name="create_date" readonly="1"/>
|
||||
</group>
|
||||
<group string="Feedback">
|
||||
<field name="rating_ids" mode="kanban" nolabel="1">
|
||||
<kanban>
|
||||
<field name="rating"/>
|
||||
<field name="feedback"/>
|
||||
<field name="res_name"/>
|
||||
<field name="create_date"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_group_details" style="min-height: 40px">
|
||||
<img t-attf-src="rating/static/src/img/rating_#{record.rating.raw_value and record.rating.raw_value or 0}.png" class="oe_kanban_image" style="float:left; margin-right: 10px;"/>
|
||||
<span t-if="record.feedback.raw_value">
|
||||
<t t-esc="record.feedback.raw_value"/>
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</group>
|
||||
</group>
|
||||
<field name="message_ids" type="tree">
|
||||
<tree string="History">
|
||||
<field name="create_date" />
|
||||
<field name="from_id" />
|
||||
<field name="message" />
|
||||
</tree>
|
||||
</field>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Session of a channel : list view -->
|
||||
<record id="action_session_channel" model="ir.actions.act_window">
|
||||
<field name="name">Sessions</field>
|
||||
<field name="res_model">im_chat.session</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('channel_id','in',[active_id])]</field>
|
||||
<field name="context">{
|
||||
'search_default_channel_id': [active_id],
|
||||
'default_channel_id': active_id,
|
||||
}</field>
|
||||
<field name="search_view_id" ref="im_chat_session_search"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!--
|
||||
Views for im_livechat.channel
|
||||
Reference in New Issue
Block a user