diff --git a/addons/bus/__init__.py b/addons/bus/__init__.py index a64d1f14026..14ce547a094 100644 --- a/addons/bus/__init__.py +++ b/addons/bus/__init__.py @@ -1 +1,3 @@ -import bus +# -*- coding: utf-8 -*- +import models +import controllers diff --git a/addons/bus/controllers/__init__.py b/addons/bus/controllers/__init__.py new file mode 100644 index 00000000000..a84d81a791b --- /dev/null +++ b/addons/bus/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +import main diff --git a/addons/bus/controllers/main.py b/addons/bus/controllers/main.py new file mode 100644 index 00000000000..49f1b97ae77 --- /dev/null +++ b/addons/bus/controllers/main.py @@ -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) diff --git a/addons/bus/models/__init__.py b/addons/bus/models/__init__.py new file mode 100644 index 00000000000..c1c365d98c0 --- /dev/null +++ b/addons/bus/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +import bus diff --git a/addons/bus/bus.py b/addons/bus/models/bus.py similarity index 78% rename from addons/bus/bus.py rename to addons/bus/models/bus.py index a9f8fb3ca3e..00c6e71a6e0 100644 --- a/addons/bus/bus.py +++ b/addons/bus/models/bus.py @@ -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) diff --git a/addons/im_chat/__init__.py b/addons/im_chat/__init__.py index cea212f0705..14ce547a094 100644 --- a/addons/im_chat/__init__.py +++ b/addons/im_chat/__init__.py @@ -1 +1,3 @@ -import im_chat +# -*- coding: utf-8 -*- +import models +import controllers diff --git a/addons/im_chat/__openerp__.py b/addons/im_chat/__openerp__.py index fbbb4d58c2e..586fbb00c98 100644 --- a/addons/im_chat/__openerp__.py +++ b/addons/im_chat/__openerp__.py @@ -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, diff --git a/addons/im_chat/controllers/__init__.py b/addons/im_chat/controllers/__init__.py new file mode 100644 index 00000000000..12d2d759f34 --- /dev/null +++ b/addons/im_chat/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -* +import main diff --git a/addons/im_chat/controllers/main.py b/addons/im_chat/controllers/main.py new file mode 100644 index 00000000000..a643f5ac528 --- /dev/null +++ b/addons/im_chat/controllers/main.py @@ -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//'], 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) diff --git a/addons/im_chat/im_chat_data.xml b/addons/im_chat/data/im_chat_session_data.xml similarity index 100% rename from addons/im_chat/im_chat_data.xml rename to addons/im_chat/data/im_chat_session_data.xml diff --git a/addons/im_chat/models/__init__.py b/addons/im_chat/models/__init__.py new file mode 100644 index 00000000000..1ee6a543eb9 --- /dev/null +++ b/addons/im_chat/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +import im_chat_session +import res_users diff --git a/addons/im_chat/im_chat.py b/addons/im_chat/models/im_chat_session.py similarity index 76% rename from addons/im_chat/im_chat.py rename to addons/im_chat/models/im_chat_session.py index 07292c8b7f9..39948ebb07e 100644 --- a/addons/im_chat/im_chat.py +++ b/addons/im_chat/models/im_chat_session.py @@ -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//'], 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) diff --git a/addons/im_chat/models/res_users.py b/addons/im_chat/models/res_users.py new file mode 100644 index 00000000000..7fda73a0b76 --- /dev/null +++ b/addons/im_chat/models/res_users.py @@ -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 \ No newline at end of file diff --git a/addons/im_chat/security/im_security.xml b/addons/im_chat/security/im_chat_session_security.xml similarity index 100% rename from addons/im_chat/security/im_security.xml rename to addons/im_chat/security/im_chat_session_security.xml diff --git a/addons/im_chat/static/src/css/im_chat.css b/addons/im_chat/static/src/css/im_chat_backend.css similarity index 100% rename from addons/im_chat/static/src/css/im_chat.css rename to addons/im_chat/static/src/css/im_chat_backend.css diff --git a/addons/im_chat/static/src/css/im_common.css b/addons/im_chat/static/src/css/im_chat_common.css similarity index 100% rename from addons/im_chat/static/src/css/im_common.css rename to addons/im_chat/static/src/css/im_chat_common.css diff --git a/addons/im_chat/static/src/js/im_chat.js b/addons/im_chat/static/src/js/im_chat_backend.js similarity index 100% rename from addons/im_chat/static/src/js/im_chat.js rename to addons/im_chat/static/src/js/im_chat_backend.js diff --git a/addons/im_chat/views/im_chat.xml b/addons/im_chat/views/im_chat_session_templates.xml similarity index 85% rename from addons/im_chat/views/im_chat.xml rename to addons/im_chat/views/im_chat_session_templates.xml index 59d67e6a2d1..c2d9a0244f2 100644 --- a/addons/im_chat/views/im_chat.xml +++ b/addons/im_chat/views/im_chat_session_templates.xml @@ -4,10 +4,10 @@ diff --git a/addons/im_chat/views/im_chat_view.xml b/addons/im_chat/views/im_chat_session_views.xml similarity index 100% rename from addons/im_chat/views/im_chat_view.xml rename to addons/im_chat/views/im_chat_session_views.xml diff --git a/addons/im_livechat/__init__.py b/addons/im_livechat/__init__.py index afed36aa655..66b01696f08 100644 --- a/addons/im_livechat/__init__.py +++ b/addons/im_livechat/__init__.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import controllers -import im_livechat -import report \ No newline at end of file +import models +import report diff --git a/addons/im_livechat/__openerp__.py b/addons/im_livechat/__openerp__.py index 1783a8e52e4..6cccfaec9f7 100644 --- a/addons/im_livechat/__openerp__.py +++ b/addons/im_livechat/__openerp__.py @@ -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, diff --git a/addons/im_livechat/controllers/__init__.py b/addons/im_livechat/controllers/__init__.py index 986caac7d6f..a84d81a791b 100644 --- a/addons/im_livechat/controllers/__init__.py +++ b/addons/im_livechat/controllers/__init__.py @@ -1,3 +1,2 @@ # -*- coding: utf-8 -*- -import livechat -import rating +import main diff --git a/addons/im_livechat/controllers/livechat.py b/addons/im_livechat/controllers/main.py similarity index 72% rename from addons/im_livechat/controllers/livechat.py rename to addons/im_livechat/controllers/main.py index bcd6ee785f9..db18dadaff5 100644 --- a/addons/im_livechat/controllers/livechat.py +++ b/addons/im_livechat/controllers/main.py @@ -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 diff --git a/addons/im_livechat/controllers/rating.py b/addons/im_livechat/controllers/rating.py deleted file mode 100644 index 508eddfe82d..00000000000 --- a/addons/im_livechat/controllers/rating.py +++ /dev/null @@ -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 diff --git a/addons/im_livechat/im_livechat_data.xml b/addons/im_livechat/data/im_livechat_channel_data.xml similarity index 100% rename from addons/im_livechat/im_livechat_data.xml rename to addons/im_livechat/data/im_livechat_channel_data.xml diff --git a/addons/im_livechat/im_livechat_demo.xml b/addons/im_livechat/data/im_livechat_channel_demo.xml similarity index 100% rename from addons/im_livechat/im_livechat_demo.xml rename to addons/im_livechat/data/im_livechat_channel_demo.xml diff --git a/addons/im_livechat/models/__init__.py b/addons/im_livechat/models/__init__.py new file mode 100644 index 00000000000..4caf13411c9 --- /dev/null +++ b/addons/im_livechat/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -* +import im_livechat_channel +import im_chat_session +import rating diff --git a/addons/im_livechat/models/im_chat_session.py b/addons/im_livechat/models/im_chat_session.py new file mode 100644 index 00000000000..fd02df0ec84 --- /dev/null +++ b/addons/im_livechat/models/im_chat_session.py @@ -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) diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/models/im_livechat_channel.py similarity index 94% rename from addons/im_livechat/im_livechat.py rename to addons/im_livechat/models/im_livechat_channel.py index 91c02810591..06f5fb5eb88 100644 --- a/addons/im_livechat/im_livechat.py +++ b/addons/im_livechat/models/im_livechat_channel.py @@ -1,24 +1,4 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - import openerp import openerp.addons.im_chat.im_chat import random diff --git a/addons/im_livechat/models/rating.py b/addons/im_livechat/models/rating.py new file mode 100644 index 00000000000..a7d1cf0531c --- /dev/null +++ b/addons/im_livechat/models/rating.py @@ -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() + diff --git a/addons/im_livechat/report/im_livechat_report.xml b/addons/im_livechat/report/im_livechat_report_views.xml similarity index 100% rename from addons/im_livechat/report/im_livechat_report.xml rename to addons/im_livechat/report/im_livechat_report_views.xml diff --git a/addons/im_livechat/security/im_livechat_security.xml b/addons/im_livechat/security/im_livechat_channel_security.xml similarity index 100% rename from addons/im_livechat/security/im_livechat_security.xml rename to addons/im_livechat/security/im_livechat_channel_security.xml diff --git a/addons/im_livechat/views/im_chat_session_views.xml b/addons/im_livechat/views/im_chat_session_views.xml new file mode 100644 index 00000000000..294d43c40a2 --- /dev/null +++ b/addons/im_livechat/views/im_chat_session_views.xml @@ -0,0 +1,91 @@ + + + + + + + History + im_chat.session + form + list,form + [('channel_id', '!=', None)] + {'group_by': ['channel_id', 'create_date:month']} + + + + im_chat.session.search + im_chat.session + + + + + + + + + + + + + + + + + im_chat.session.tree + im_chat.session + + + + + + + + + + + im_chat.session.form + im_chat.session + +
+ + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+
+
+
+ + + + + + + +
+
+
+
+ +
+
diff --git a/addons/im_livechat/views/im_livechat.xml b/addons/im_livechat/views/im_livechat_channel_templates.xml similarity index 99% rename from addons/im_livechat/views/im_livechat.xml rename to addons/im_livechat/views/im_livechat_channel_templates.xml index b08fa0744aa..e9b83daa70a 100644 --- a/addons/im_livechat/views/im_livechat.xml +++ b/addons/im_livechat/views/im_livechat_channel_templates.xml @@ -139,7 +139,7 @@ - + diff --git a/addons/im_livechat/views/im_livechat_view.xml b/addons/im_livechat/views/im_livechat_channel_views.xml similarity index 66% rename from addons/im_livechat/views/im_livechat_view.xml rename to addons/im_livechat/views/im_livechat_channel_views.xml index 3ffeb68b637..964c7a897c6 100644 --- a/addons/im_livechat/views/im_livechat_view.xml +++ b/addons/im_livechat/views/im_livechat_channel_views.xml @@ -1,108 +1,6 @@ - - - - History - im_chat.session - form - list,form - [('channel_id', '!=', None)] - {'group_by': ['channel_id', 'create_date:month']} - - - - im_chat.session.search - im_chat.session - - - - - - - - - - - - - - - - - im_chat.session.tree - im_chat.session - - - - - - - - - - - im_chat.session.form - im_chat.session - -
- - - - - - - - - - - - - - - - -
- - - - -
-
-
-
-
-
-
- - - - - - - -
-
-
-
- - - - - Sessions - im_chat.session - list,form - [('channel_id','in',[active_id])] - { - 'search_default_channel_id': [active_id], - 'default_channel_id': active_id, - } - - -