diff --git a/asterisk_click2dial/__init__.py b/asterisk_click2dial/__init__.py index 11a14a7..2a24f08 100644 --- a/asterisk_click2dial/__init__.py +++ b/asterisk_click2dial/__init__.py @@ -1,23 +1,4 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Asterisk Click2Dial module for OpenERP -# Copyright (C) 2010-2013 Alexis de Lattre -# -# 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 . -# -############################################################################## from . import asterisk_click2dial from . import controller diff --git a/asterisk_click2dial/__openerp__.py b/asterisk_click2dial/__openerp__.py index 5d9dd7b..5859643 100644 --- a/asterisk_click2dial/__openerp__.py +++ b/asterisk_click2dial/__openerp__.py @@ -1,33 +1,15 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Asterisk Click2dial module for OpenERP -# Copyright (C) 2010-2014 Alexis de Lattre -# -# 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 . -# -############################################################################## - +# -*- coding: utf-8 -*- +# © 2010-2016 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { 'name': 'Asterisk Click2dial', - 'version': '8.0.0.4.0', + 'version': '9.0.1.0.0', 'category': 'Phone', 'license': 'AGPL-3', - 'summary': 'Asterisk-OpenERP connector', + 'summary': 'Asterisk-Odoo connector', 'description': """ -Asterisk-OpenERP connector +Asterisk-Odoo connector ========================== The technical name of this module is *asterisk_click2dial*, but this module @@ -38,21 +20,21 @@ functionalities: dial a phone number through Asterisk. This feature is usually known as *click2dial*. Here is how it works : - * In OpenERP, the user clicks on the *Dial* button next to a phone number + * In Odoo, the user clicks on the *Dial* button next to a phone number field in the partner view. - * OpenERP connects to the Asterisk Manager Interface and Asterisk makes the + * Odoo connects to the Asterisk Manager Interface and Asterisk makes the user's phone ring. * The user answers his own phone (if he doesn't, the process stops here). - * Asterisk dials the phone number found in OpenERP in place of the user. + * Asterisk dials the phone number found in Odoo in place of the user. * If the remote party answers, the user can talk to his correspondent. 2) It adds the ability to show the name of the calling party on the screen of your IP phone on incoming phone calls if the presented phone number is - present in the partner/leads/employees/... of OpenERP. Here is how it works: + present in the partner/leads/employees/... of Odoo. Here is how it works: * On incoming phone calls, the Asterisk dialplan executes an AGI script "set_name_incoming_timeout.sh". @@ -60,7 +42,7 @@ functionalities: * The "set_name_incoming_timeout.sh" script calls the "set_name_agi.py" script with a short timeout. - * The "set_name_agi.py" script will make an XML-RPC request on the OpenERP + * The "set_name_agi.py" script will make an XML-RPC request on the Odoo server to try to find the name of the person corresponding to the phone number presented by the calling party. @@ -75,14 +57,14 @@ functionalities: (next to the Preferences) to get the partner/lead/candidate/registrations corresponding to the calling party in one click. Here is how it works : - * When the user clicks on the phone icon, OpenERP sends a query to the + * When the user clicks on the phone icon, Odoo sends a query to the Asterisk Manager Interface to get a list of the current phone calls * If it finds a phone call involving the user's phone, it gets the phone number of the calling party * It searches the phone number of the calling party in the - Partners/Leads/Candidates/Registrations of OpenERP. If a record matches, + Partners/Leads/Candidates/Registrations of Odoo. If a record matches, it takes you to the form view of this record. If no record matchs, it opens a wizard which proposes to create a new Partner with the presented phone number as *Phone* or *Mobile* number or update an existing Partner. @@ -107,6 +89,5 @@ http://www.akretion.com/products-and-services/openerp-asterisk-voip-connector 'qweb': ['static/src/xml/*.xml'], 'css': ['static/src/css/*.css'], 'application': True, - 'installable': False, - 'active': False, + 'installable': True, } diff --git a/asterisk_click2dial/asterisk_click2dial.py b/asterisk_click2dial/asterisk_click2dial.py index e9c9d9f..adce5a9 100644 --- a/asterisk_click2dial/asterisk_click2dial.py +++ b/asterisk_click2dial/asterisk_click2dial.py @@ -1,31 +1,13 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Asterisk Click2dial module for OpenERP -# Copyright (C) 2010-2013 Alexis de Lattre -# -# 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 . -# -############################################################################## - -from openerp.osv import fields, orm -from openerp.tools.translate import _ +# -*- coding: utf-8 -*- +# © 2010-2016 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp import models, fields, api, _ +from openerp.exceptions import UserError, ValidationError import logging try: - # Lib py-asterisk from http://code.google.com/p/py-asterisk/ - # -> pip install py-Asterisk + # pip install py-Asterisk from Asterisk import Manager except ImportError: Manager = None @@ -33,73 +15,66 @@ except ImportError: _logger = logging.getLogger(__name__) -class asterisk_server(orm.Model): +class AsteriskServer(models.Model): '''Asterisk server object, stores the parameters of the Asterisk IPBXs''' _name = "asterisk.server" _description = "Asterisk Servers" - _columns = { - 'name': fields.char('Asterisk Server Name', size=50, required=True), - 'active': fields.boolean( - 'Active', help="The active field allows you to hide the Asterisk " - "server without deleting it."), - 'ip_address': fields.char( - 'Asterisk IP address or DNS', size=50, required=True, - help="IP address or DNS name of the Asterisk server."), - 'port': fields.integer( - 'Port', required=True, - help="TCP port on which the Asterisk Manager Interface listens. " - "Defined in /etc/asterisk/manager.conf on Asterisk."), - 'out_prefix': fields.char( - 'Out Prefix', size=4, help="Prefix to dial to make outgoing " - "calls. If you don't use a prefix to make outgoing calls, " - "leave empty."), - 'login': fields.char( - 'AMI Login', size=30, required=True, - help="Login that OpenERP will use to communicate with the " - "Asterisk Manager Interface. Refer to /etc/asterisk/manager.conf " - "on your Asterisk server."), - 'password': fields.char( - 'AMI Password', size=30, required=True, - help="Password that OpenERP will use to communicate with the " - "Asterisk Manager Interface. Refer to /etc/asterisk/manager.conf " - "on your Asterisk server."), - 'context': fields.char( - 'Dialplan Context', size=50, required=True, - help="Asterisk dialplan context from which the calls will be " - "made. Refer to /etc/asterisk/extensions.conf on your Asterisk " - "server."), - 'wait_time': fields.integer( - 'Wait Time (sec)', required=True, - help="Amount of time (in seconds) Asterisk will try to reach " - "the user's phone before hanging up."), - 'extension_priority': fields.integer( - 'Extension Priority', required=True, - help="Priority of the extension in the Asterisk dialplan. Refer " - "to /etc/asterisk/extensions.conf on your Asterisk server."), - 'alert_info': fields.char( - 'Alert-Info SIP Header', size=255, - help="Set Alert-Info header in SIP request to user's IP Phone " - "for the click2dial feature. If empty, the Alert-Info header " - "will not be added. You can use it to have a special ring tone " - "for click2dial (a silent one !) or to activate auto-answer " - "for example."), - 'company_id': fields.many2one( - 'res.company', 'Company', - help="Company who uses the Asterisk server."), - } - - _defaults = { - 'active': True, - 'port': 5038, # Default AMI port - 'extension_priority': 1, - 'wait_time': 15, - 'company_id': lambda self, cr, uid, context: - self.pool['res.company']._company_default_get( - cr, uid, 'asterisk.server', context=context), - } - - def _check_validity(self, cr, uid, ids): - for server in self.browse(cr, uid, ids): + + name = fields.Char(string='Asterisk Server Name', required=True) + active = fields.Boolean( + string='Active', default=True) + ip_address = fields.Char( + string='Asterisk IP address or DNS', required=True) + port = fields.Integer( + string='Port', required=True, default=5038, + help="TCP port on which the Asterisk Manager Interface listens. " + "Defined in /etc/asterisk/manager.conf on Asterisk.") + out_prefix = fields.Char( + string='Out Prefix', size=4, help="Prefix to dial to make outgoing " + "calls. If you don't use a prefix to make outgoing calls, " + "leave empty.") + login = fields.Char( + string='AMI Login', required=True, + help="Login that Odoo will use to communicate with the " + "Asterisk Manager Interface. Refer to /etc/asterisk/manager.conf " + "on your Asterisk server.") + password = fields.Char( + string='AMI Password', required=True, + help="Password that Odoo will use to communicate with the " + "Asterisk Manager Interface. Refer to /etc/asterisk/manager.conf " + "on your Asterisk server.") + context = fields.Char( + string='Dialplan Context', required=True, + help="Asterisk dialplan context from which the calls will be " + "made. Refer to /etc/asterisk/extensions.conf on your Asterisk " + "server.") + wait_time = fields.Integer( + string='Wait Time', required=True, default=15, + help="Amount of time (in seconds) Asterisk will try to reach " + "the user's phone before hanging up.") + extension_priority = fields.Integer( + string='Extension Priority', required=True, default=1, + help="Priority of the extension in the Asterisk dialplan. Refer " + "to /etc/asterisk/extensions.conf on your Asterisk server.") + alert_info = fields.Char( + string='Alert-Info SIP Header', + help="Set Alert-Info header in SIP request to user's IP Phone " + "for the click2dial feature. If empty, the Alert-Info header " + "will not be added. You can use it to have a special ring tone " + "for click2dial (a silent one !) or to activate auto-answer " + "for example.") + company_id = fields.Many2one( + 'res.company', string='Company', + default=lambda self: self.env['res.company']._company_default_get( + 'asterisk.server'), + help="Company who uses the Asterisk server.") + + @api.multi + @api.constrains( + 'out_prefix', 'wait_time', 'extension_priority', 'port', + 'context', 'alert_info', 'login', 'password') + def _check_validity(self): + for server in self: out_prefix = ('Out prefix', server.out_prefix) dialplan_context = ('Dialplan context', server.context) alert_info = ('Alert-Info SIP header', server.alert_info) @@ -107,23 +82,19 @@ class asterisk_server(orm.Model): password = ('AMI password', server.password) if out_prefix[1] and not out_prefix[1].isdigit(): - raise orm.except_orm( - _('Error:'), + raise ValidationError( _("Only use digits for the '%s' on the Asterisk server " "'%s'" % (out_prefix[0], server.name))) if server.wait_time < 1 or server.wait_time > 120: - raise orm.except_orm( - _('Error:'), + raise ValidationError( _("You should set a 'Wait time' value between 1 and 120 " "seconds for the Asterisk server '%s'" % server.name)) if server.extension_priority < 1: - raise orm.except_orm( - _('Error:'), + raise ValidationError( _("The 'extension priority' must be a positive value for " "the Asterisk server '%s'" % server.name)) if server.port > 65535 or server.port < 1: - raise orm.except_orm( - _('Error:'), + raise ValidationError( _("You should set a TCP port between 1 and 65535 for the " "Asterisk server '%s'" % server.name)) for check_str in [dialplan_context, alert_info, login, password]: @@ -131,70 +102,34 @@ class asterisk_server(orm.Model): try: check_str[1].encode('ascii') except UnicodeEncodeError: - raise orm.except_orm( - _('Error:'), + raise ValidationError( _("The '%s' should only have ASCII caracters for " "the Asterisk server '%s'" % (check_str[0], server.name))) - return True - - _constraints = [( - _check_validity, - "Error message in raise", - [ - 'out_prefix', 'wait_time', 'extension_priority', 'port', - 'context', 'alert_info', 'login', 'password'] - )] - - def _get_asterisk_server_from_user(self, cr, uid, context=None): - '''Returns an asterisk.server browse object''' - # We check if the user has an Asterisk server configured - user = self.pool['res.users'].browse(cr, uid, uid, context=context) - if user.asterisk_server_id.id: - ast_server = user.asterisk_server_id - else: - asterisk_server_ids = self.search( - cr, uid, [('company_id', '=', user.company_id.id)], - context=context) - # If the user doesn't have an asterisk server, - # we take the first one of the user's company - if not asterisk_server_ids: - raise orm.except_orm( - _('Error:'), - _("No Asterisk server configured for the company '%s'.") - % user.company_id.name) - else: - ast_server = self.browse( - cr, uid, asterisk_server_ids[0], context=context) - return ast_server - def _connect_to_asterisk(self, cr, uid, context=None): + @api.model + def _connect_to_asterisk(self): ''' Open the connection to the Asterisk Manager Returns an instance of the Asterisk Manager ''' - user = self.pool['res.users'].browse(cr, uid, uid, context=context) - - ast_server = self._get_asterisk_server_from_user( - cr, uid, context=context) + user = self.env.user + ast_server = user.get_asterisk_server_from_user() # We check if the current user has a chan type if not user.asterisk_chan_type: - raise orm.except_orm( - _('Error:'), + raise UserError( _('No channel type configured for the current user.')) # We check if the current user has an internal number if not user.resource: - raise orm.except_orm( - _('Error:'), + raise UserError( _('No resource name configured for the current user')) _logger.debug( - "User's phone: %s/%s" % (user.asterisk_chan_type, user.resource)) + "User's phone: %s/%s", user.asterisk_chan_type, user.resource) _logger.debug( - "Asterisk server: %s:%d" - % (ast_server.ip_address, ast_server.port)) + "Asterisk server: %s:%d", ast_server.ip_address, ast_server.port) # Connect to the Asterisk Manager Interface try: @@ -203,41 +138,38 @@ class asterisk_server(orm.Model): ast_server.login, ast_server.password) except Exception, e: _logger.error( - "Error in the request to the Asterisk Manager Interface %s" - % ast_server.ip_address) - _logger.error("Here is the error message: %s" % e) - raise orm.except_orm( - _('Error:'), - _("Problem in the request from OpenERP to Asterisk. " + "Error in the request to the Asterisk Manager Interface %s", + ast_server.ip_address) + _logger.error("Here is the error message: %s", e) + raise UserError( + _("Problem in the request from Odoo to Asterisk. " "Here is the error message: %s" % e)) return (user, ast_server, ast_manager) - def test_ami_connection(self, cr, uid, ids, context=None): - assert len(ids) == 1, 'Only 1 ID' - ast_server = self.browse(cr, uid, ids[0], context=context) + @api.multi + def test_ami_connection(self): + self.ensure_one() ast_manager = False try: ast_manager = Manager.Manager( - (ast_server.ip_address, ast_server.port), - ast_server.login, - ast_server.password) + (self.ip_address, self.port), + self.login, + self.password) except Exception, e: - raise orm.except_orm( - _("Connection Test Failed!"), - _("Here is the error message: %s" % e)) + raise UserError( + _("Connection Test Failed! The error message is: %s" % e)) finally: if ast_manager: ast_manager.Logoff() - raise orm.except_orm( - _("Connection Test Successfull!"), - _("Odoo can successfully login to the Asterisk Manager " - "Interface.")) + raise UserError(_( + "Connection Test Successfull! Odoo can successfully login to " + "the Asterisk Manager Interface.")) - def _get_calling_number(self, cr, uid, context=None): + @api.model + def _get_calling_number(self): - user, ast_server, ast_manager = self._connect_to_asterisk( - cr, uid, context=context) + user, ast_server, ast_manager = self._connect_to_asterisk() calling_party_number = False try: list_chan = ast_manager.Status() @@ -255,42 +187,41 @@ class asterisk_server(orm.Model): break # 6 = Up if ( - chan.get('ChannelState') == '6' - and sip_account in chan.get('BridgedChannel', '')): + chan.get('ChannelState') == '6' and + sip_account in chan.get('BridgedChannel', '')): _logger.debug("Found a matching Event in 'Up' state") calling_party_number = chan.get('CallerIDNum') break # Compatibility with Asterisk 1.4 if ( - chan.get('State') == 'Up' - and sip_account in chan.get('Link', '')): + chan.get('State') == 'Up' and + sip_account in chan.get('Link', '')): _logger.debug("Found a matching Event in 'Up' state") calling_party_number = chan.get('CallerIDNum') break except Exception, e: _logger.error( - "Error in the Status request to Asterisk server %s" - % ast_server.ip_address) + "Error in the Status request to Asterisk server %s", + ast_server.ip_address) _logger.error( - "Here are the details of the error: '%s'" % unicode(e)) - raise orm.except_orm( - _('Error:'), + "Here are the details of the error: '%s'", unicode(e)) + raise UserError( _("Can't get calling number from Asterisk.\nHere is the " "error: '%s'" % unicode(e))) finally: ast_manager.Logoff() - _logger.debug("Calling party number: '%s'" % calling_party_number) + _logger.debug("Calling party number: '%s'", calling_party_number) return calling_party_number - def get_record_from_my_channel(self, cr, uid, context=None): - calling_number = self.pool['asterisk.server']._get_calling_number( - cr, uid, context=context) + @api.model + def get_record_from_my_channel(self): + calling_number = self.env['asterisk.server']._get_calling_number() # calling_number = "0641981246" if calling_number: - record = self.pool['phone.common'].get_record_from_phone_number( - cr, uid, calling_number, context=context) + record = self.env['phone.common'].get_record_from_phone_number( + calling_number) if record: return record else: @@ -299,75 +230,72 @@ class asterisk_server(orm.Model): return False -class res_users(orm.Model): +class ResUsers(models.Model): _inherit = "res.users" - _columns = { - 'internal_number': fields.char( - 'Internal Number', size=15, - help="User's internal phone number."), - 'dial_suffix': fields.char( - 'User-specific Dial Suffix', size=15, - help="User-specific dial suffix such as aa=2wb for SCCP " - "auto answer."), - 'callerid': fields.char( - 'Caller ID', size=50, - help="Caller ID used for the calls initiated by this user."), - # You'd probably think: Asterisk should reuse the callerID of sip.conf! - # But it cannot, cf - # http://lists.digium.com/pipermail/asterisk-users/ - # 2012-January/269787.html - 'cdraccount': fields.char( - 'CDR Account', size=50, - help="Call Detail Record (CDR) account used for billing this " - "user."), - 'asterisk_chan_type': fields.selection([ - ('SIP', 'SIP'), - ('IAX2', 'IAX2'), - ('DAHDI', 'DAHDI'), - ('Zap', 'Zap'), - ('Skinny', 'Skinny'), - ('MGCP', 'MGCP'), - ('mISDN', 'mISDN'), - ('H323', 'H323'), - ('SCCP', 'SCCP'), - ('Local', 'Local'), - ], 'Asterisk Channel Type', - help="Asterisk channel type, as used in the Asterisk dialplan. " - "If the user has a regular IP phone, the channel type is 'SIP'."), - 'resource': fields.char( - 'Resource Name', size=64, - help="Resource name for the channel type selected. For example, " - "if you use 'Dial(SIP/phone1)' in your Asterisk dialplan to ring " - "the SIP phone of this user, then the resource name for this user " - "is 'phone1'. For a SIP phone, the phone number is often used as " - "resource name, but not always."), - 'alert_info': fields.char( - 'User-specific Alert-Info SIP Header', size=255, - help="Set a user-specific Alert-Info header in SIP request to " - "user's IP Phone for the click2dial feature. If empty, the " - "Alert-Info header will not be added. You can use it to have a " - "special ring tone for click2dial (a silent one !) or to " - "activate auto-answer for example."), - 'variable': fields.char( - 'User-specific Variable', size=255, - help="Set a user-specific 'Variable' field in the Asterisk " - "Manager Interface 'originate' request for the click2dial " - "feature. If you want to have several variable headers, separate " - "them with '|'."), - 'asterisk_server_id': fields.many2one( - 'asterisk.server', 'Asterisk Server', - help="Asterisk server on which the user's phone is connected. " - "If you leave this field empty, it will use the first Asterisk " - "server of the user's company."), - } - - _defaults = { - 'asterisk_chan_type': 'SIP', - } - - def _check_validity(self, cr, uid, ids): - for user in self.browse(cr, uid, ids): + internal_number = fields.Char( + string='Internal Number', copy=False, + help="User's internal phone number.") + dial_suffix = fields.Char( + string='User-specific Dial Suffix', + help="User-specific dial suffix such as aa=2wb for SCCP auto answer.") + callerid = fields.Char( + string='Caller ID', copy=False, + help="Caller ID used for the calls initiated by this user.") + # You'd probably think: Asterisk should reuse the callerID of sip.conf! + # But it cannot, cf + # http://lists.digium.com/pipermail/asterisk-users/ + # 2012-January/269787.html + cdraccount = fields.Char( + string='CDR Account', + help="Call Detail Record (CDR) account used for billing this user.") + asterisk_chan_type = fields.Selection([ + ('SIP', 'SIP'), + ('IAX2', 'IAX2'), + ('DAHDI', 'DAHDI'), + ('Zap', 'Zap'), + ('Skinny', 'Skinny'), + ('MGCP', 'MGCP'), + ('mISDN', 'mISDN'), + ('H323', 'H323'), + ('SCCP', 'SCCP'), + # Local works for click2dial, but it won't work in + # _get_calling_number() when trying to identify the + # channel of the user, so it's better not to propose it + # ('Local', 'Local'), + ], string='Asterisk Channel Type', default='SIP', + help="Asterisk channel type, as used in the Asterisk dialplan. " + "If the user has a regular IP phone, the channel type is 'SIP'.") + resource = fields.Char( + string='Resource Name', copy=False, + help="Resource name for the channel type selected. For example, " + "if you use 'Dial(SIP/phone1)' in your Asterisk dialplan to ring " + "the SIP phone of this user, then the resource name for this user " + "is 'phone1'. For a SIP phone, the phone number is often used as " + "resource name, but not always.") + alert_info = fields.Char( + string='User-specific Alert-Info SIP Header', + help="Set a user-specific Alert-Info header in SIP request to " + "user's IP Phone for the click2dial feature. If empty, the " + "Alert-Info header will not be added. You can use it to have a " + "special ring tone for click2dial (a silent one !) or to " + "activate auto-answer for example.") + variable = fields.Char( + string='User-specific Variable', + help="Set a user-specific 'Variable' field in the Asterisk " + "Manager Interface 'originate' request for the click2dial " + "feature. If you want to have several variable headers, separate " + "them with '|'.") + asterisk_server_id = fields.Many2one( + 'asterisk.server', string='Asterisk Server', + help="Asterisk server on which the user's phone is connected. " + "If you leave this field empty, it will use the first Asterisk " + "server of the user's company.") + + @api.multi + @api.constrains('resource', 'internal_number', 'callerid') + def _check_validity(self): + for user in self: strings_to_check = [ (_('Resource Name'), user.resource), (_('Internal Number'), user.internal_number), @@ -378,47 +306,53 @@ class res_users(orm.Model): try: check_string[1].encode('ascii') except UnicodeEncodeError: - raise orm.except_orm( - _('Error:'), - _("The '%s' for the user '%s' should only have " - "ASCII caracters") + raise ValidationError(_( + "The '%s' for the user '%s' should only have " + "ASCII caracters") % (check_string[0], user.name)) - return True - _constraints = [( - _check_validity, - "Error message in raise", - ['resource', 'internal_number', 'callerid'] - )] + @api.multi + def get_asterisk_server_from_user(self): + '''Returns an asterisk.server recordset''' + self.ensure_one() + # We check if the user has an Asterisk server configured + if self.asterisk_server_id: + ast_server = self.asterisk_server_id + else: + asterisk_servers = self.env['asterisk.server'].search( + [('company_id', '=', self.company_id.id)]) + # If the user doesn't have an asterisk server, + # we take the first one of the user's company + if not asterisk_servers: + raise UserError( + _("No Asterisk server configured for the company '%s'.") + % self.company_id.name) + else: + ast_server = asterisk_servers[0] + return ast_server -class PhoneCommon(orm.AbstractModel): +class PhoneCommon(models.AbstractModel): _inherit = 'phone.common' - def click2dial(self, cr, uid, erp_number, context=None): - res = super(PhoneCommon, self).click2dial( - cr, uid, erp_number, context=context) + @api.model + def click2dial(self, erp_number): + res = super(PhoneCommon, self).click2dial(erp_number) if not erp_number: - raise orm.except_orm( - _('Error:'), - _('Missing phone number')) + raise UserError(_('Missing phone number')) user, ast_server, ast_manager = \ - self.pool['asterisk.server']._connect_to_asterisk( - cr, uid, context=context) - ast_number = self.convert_to_dial_number( - cr, uid, erp_number, context=context) + self.env['asterisk.server']._connect_to_asterisk() + ast_number = self.convert_to_dial_number(erp_number) # Add 'out prefix' if ast_server.out_prefix: - _logger.debug('Out prefix = %s' % ast_server.out_prefix) + _logger.debug('Out prefix = %s', ast_server.out_prefix) ast_number = '%s%s' % (ast_server.out_prefix, ast_number) - _logger.debug('Number to be sent to Asterisk = %s' % ast_number) + _logger.debug('Number to be sent to Asterisk = %s', ast_number) # The user should have a CallerID if not user.callerid: - raise orm.except_orm( - _('Error:'), - _('No callerID configured for the current user')) + raise UserError(_('No callerID configured for the current user')) variable = [] if user.asterisk_chan_type == 'SIP': @@ -441,19 +375,18 @@ class PhoneCommon(orm.AbstractModel): channel, context=ast_server.context, extension=ast_number, - priority=str(ast_server.extension_priority), - timeout=str(ast_server.wait_time * 1000), + priority=unicode(ast_server.extension_priority), + timeout=unicode(ast_server.wait_time * 1000), caller_id=user.callerid, account=user.cdraccount, variable=variable) except Exception, e: _logger.error( - "Error in the Originate request to Asterisk server %s" - % ast_server.ip_address) + "Error in the Originate request to Asterisk server %s", + ast_server.ip_address) _logger.error( - "Here are the details of the error: '%s'" % unicode(e)) - raise orm.except_orm( - _('Error:'), + "Here are the details of the error: '%s'", unicode(e)) + raise UserError( _("Click to dial with Asterisk failed.\nHere is the error: " "'%s'") % unicode(e)) diff --git a/asterisk_click2dial/asterisk_click2dial_demo.xml b/asterisk_click2dial/asterisk_click2dial_demo.xml index 80e76ac..a808e42 100644 --- a/asterisk_click2dial/asterisk_click2dial_demo.xml +++ b/asterisk_click2dial/asterisk_click2dial_demo.xml @@ -1,38 +1,41 @@ - - - - Akretion Asterisk IPBX - asterisk.akretion.com - click2dial - mypassword - from-internal - info=<Bellcore-dr5> - - - - 11 - 11 - Administrator <0141981242> - - - - 12 - 12 - Demo user <0141984212> - - - - - - - + + + + + + Akretion Asterisk IPBX + asterisk.akretion.com + odoo + mypassword + from-internal + info=<Bellcore-dr5> + + + + + 11 + 11 + Administrator <0141981242> + + + + + 12 + 12 + Demo user <0141984212> + + + + + + + + + diff --git a/asterisk_click2dial/asterisk_server_view.xml b/asterisk_click2dial/asterisk_server_view.xml index 5c55a82..d095a82 100644 --- a/asterisk_click2dial/asterisk_server_view.xml +++ b/asterisk_click2dial/asterisk_server_view.xml @@ -1,14 +1,13 @@ - + - asterisk.server.search asterisk.server @@ -20,12 +19,11 @@ - asterisk.server.form asterisk.server -
+