From e60a818fcbda58ec47987028f768d6578c5ff94b Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Wed, 20 May 2015 14:12:11 +0200 Subject: [PATCH 1/2] Please welcome the new module ovh_telephony_connector ! Some code clean-up and re-organisation in the generic modules Prepare the removal of the module asterisk_click2dial_crm --- README.md | 17 +-- asterisk_click2dial/asterisk_click2dial.py | 7 +- asterisk_click2dial_crm/__init__.py | 2 - asterisk_click2dial_crm/__openerp__.py | 30 ++--- .../asterisk_click2dial_crm.py | 45 -------- .../i18n/asterisk_click2dial_crm.pot | 88 --------------- asterisk_click2dial_crm/i18n/ca.po | 44 -------- asterisk_click2dial_crm/i18n/es.po | 44 -------- asterisk_click2dial_crm/i18n/fr.po | 88 --------------- asterisk_click2dial_crm/res_users_view.xml | 23 ---- .../static/description/icon.png | Bin 16778 -> 0 bytes base_phone/base_phone.py | 4 +- base_phone/controller.py | 4 +- base_phone/static/src/xml/phone.xml | 3 +- base_phone/wizard/number_not_found.py | 7 +- base_phone/wizard/number_not_found_view.xml | 3 +- crm_phone/crm_phone.py | 19 +++- crm_phone/res_users_view.xml | 4 +- crm_phone/wizard/number_not_found.py | 4 +- ovh_telephony_connector/__init__.py | 22 ++++ ovh_telephony_connector/__openerp__.py | 39 +++++++ ovh_telephony_connector/ovh_connector.py | 104 ++++++++++++++++++ ovh_telephony_connector/res_users_view.xml | 42 +++++++ .../static/src/xml/ovh_connector.xml | 17 +++ 24 files changed, 278 insertions(+), 382 deletions(-) delete mode 100644 asterisk_click2dial_crm/asterisk_click2dial_crm.py delete mode 100644 asterisk_click2dial_crm/i18n/asterisk_click2dial_crm.pot delete mode 100644 asterisk_click2dial_crm/i18n/ca.po delete mode 100644 asterisk_click2dial_crm/i18n/es.po delete mode 100644 asterisk_click2dial_crm/i18n/fr.po delete mode 100644 asterisk_click2dial_crm/res_users_view.xml delete mode 100644 asterisk_click2dial_crm/static/description/icon.png create mode 100644 ovh_telephony_connector/__init__.py create mode 100644 ovh_telephony_connector/__openerp__.py create mode 100644 ovh_telephony_connector/ovh_connector.py create mode 100644 ovh_telephony_connector/res_users_view.xml create mode 100644 ovh_telephony_connector/static/src/xml/ovh_connector.xml diff --git a/README.md b/README.md index 5fb9db7..2bf7b19 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,18 @@ [![Build Status](https://travis-ci.org/OCA/connector-telephony.svg?branch=8.0)](https://travis-ci.org/OCA/connector-telephony) [![Coverage Status](https://coveralls.io/repos/OCA/connector-telephony/badge.png?branch=8.0)](https://coveralls.io/r/OCA/connector-telephony?branch=8.0) -# Odoo-Asterisk connector +# Odoo telephony connector -Asterisk is an OpenSource software for telephony. -It is used worldwide to run IPBXes inside companies. -This project connects Asterisk to Odoo/OpenERP. +This projets aims at connecting Odoo to different phone systems. Phone systems currently supported are Asterisk (an OpenSource IPBX, cf [asterisk.org](http://www.asterisk.org/) and OVH (the centrex offer of OVH, cf the [OVH website](http://www.ovhtelecom.fr/telephonie/)). -This project also provides a serie of modules (base\_phone, base\_phone\_popup, -crm\_phone, hr\_phone, event\_phone, etc...) that are independant from -Asterisk and can be usefull on all Odoo/OpenERP installations. +This project provides: +* a serie of modules (base\_phone, base\_phone\_popup, + crm\_phone, hr\_phone, event\_phone, etc...) that are independant from + the phone system and can be usefull on all Odoo installations. +* several modules (asterisk\_click2dial, ovh\_telephony\_connector) + that are specific to a particular phone system. -The main maintainer of the Asterisk-OpenERP connector is Alexis de Lattre from +The main maintainer of this project is Alexis de Lattre from Akretion (alexis.delattre \_at\_ akretion.com). To know more about the OpenERP-Asterisk connector, refer to the documentation diff --git a/asterisk_click2dial/asterisk_click2dial.py b/asterisk_click2dial/asterisk_click2dial.py index 0babd4d..e9c9d9f 100644 --- a/asterisk_click2dial/asterisk_click2dial.py +++ b/asterisk_click2dial/asterisk_click2dial.py @@ -392,10 +392,12 @@ class res_users(orm.Model): )] -class phone_common(orm.AbstractModel): +class PhoneCommon(orm.AbstractModel): _inherit = 'phone.common' def click2dial(self, cr, uid, erp_number, context=None): + res = super(PhoneCommon, self).click2dial( + cr, uid, erp_number, context=context) if not erp_number: raise orm.except_orm( _('Error:'), @@ -458,4 +460,5 @@ class phone_common(orm.AbstractModel): finally: ast_manager.Logoff() - return {'dialed_number': ast_number} + res['dialed_number'] = ast_number + return res diff --git a/asterisk_click2dial_crm/__init__.py b/asterisk_click2dial_crm/__init__.py index a42e8f0..676d5d5 100644 --- a/asterisk_click2dial_crm/__init__.py +++ b/asterisk_click2dial_crm/__init__.py @@ -19,5 +19,3 @@ # along with this program. If not, see . # ############################################################################## - -from . import asterisk_click2dial_crm diff --git a/asterisk_click2dial_crm/__openerp__.py b/asterisk_click2dial_crm/__openerp__.py index 1e3e3dc..7f63300 100644 --- a/asterisk_click2dial_crm/__openerp__.py +++ b/asterisk_click2dial_crm/__openerp__.py @@ -31,34 +31,18 @@ Asterisk Click2dial CRM ======================= -This module adds CRM-specific features to the asterisk_click2dial module. +This module is *EMPTY* ; so you should uninstall it now. +The code that used to be in this module has been moved to the module +*crm_phone* that is available in the same GitHub repository +https://github.com/OCA/connector-telephony -It adds 2 features : - -First, when you do a click2dial, OpenERP will propose you to create an outbound -phone call in the CRM ; if you answer 'Yes', it will create the phone call in -the CRM and open it in a new tab. If some users don't want to be asked to -create a phone call in the CRM each time they do a click2dial, you should -disable the corresponding option in the 'Telephony' tab of the 'User' form. - -Second, when you receive a phone call and run the wizard -"Open calling partner", if the partner is found in OpenERP, you will see a -button that proposes to create an inbound phone call in the CRM. - -This module has been initially developped by Zikzakmedia and has been -completely re-written by Akretion. - -A detailed documentation for the OpenERP-Asterisk connector is available on the -Akretion Web site : -http://www.akretion.com/products-and-services/openerp-asterisk-voip-connector +This module will be removed from the repository in the near future. """, "depends": [ 'asterisk_click2dial', 'crm_phone', ], - "data": [ - 'res_users_view.xml', - ], + "data": [], "installable": True, - "application": True, + "application": False, } diff --git a/asterisk_click2dial_crm/asterisk_click2dial_crm.py b/asterisk_click2dial_crm/asterisk_click2dial_crm.py deleted file mode 100644 index 50e3065..0000000 --- a/asterisk_click2dial_crm/asterisk_click2dial_crm.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Asterisk click2dial CRM module for OpenERP -# Copyright (c) 2012-2014 Akretion (http://www.akretion.com) -# @author: 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 import models, api, _ - - -class PhoneCommon(models.AbstractModel): - _inherit = 'phone.common' - - @api.model - def click2dial(self, erp_number): - ''' - Inherit the native click2dial function to trigger - a wizard "Create Call in CRM" via the Javascript code - of base_phone - ''' - res = super(PhoneCommon, self).click2dial(erp_number) - if ( - self.env.context.get('click2dial_model') in - ('res.partner', 'crm.lead') and - self.env.user.context_propose_creation_crm_call): - res.update({ - 'action_name': _('Create Call in CRM'), - 'action_model': 'wizard.create.crm.phonecall', - }) - return res diff --git a/asterisk_click2dial_crm/i18n/asterisk_click2dial_crm.pot b/asterisk_click2dial_crm/i18n/asterisk_click2dial_crm.pot deleted file mode 100644 index f39ccb0..0000000 --- a/asterisk_click2dial_crm/i18n/asterisk_click2dial_crm.pot +++ /dev/null @@ -1,88 +0,0 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * asterisk_click2dial_crm -# -msgid "" -msgstr "" -"Project-Id-Version: OpenERP Server 7.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-08-25 22:02+0000\n" -"PO-Revision-Date: 2014-08-25 22:02+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "CRM phone call" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.actions.act_window,name:asterisk_click2dial_crm.action_create_crm_phonecall -msgid "Create CRM phonecall" -msgstr "" - -#. module: asterisk_click2dial_crm -#: code:addons/asterisk_click2dial_crm/asterisk_click2dial_crm.py:46 -#, python-format -msgid "Create Call in CRM" -msgstr "" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "Create a phone call in the CRM ?" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_crm_lead -msgid "Lead/Opportunity" -msgstr "" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "No" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_wizard_open_calling_partner -msgid "Open calling partner" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_res_partner -msgid "Partner" -msgstr "" - -#. module: asterisk_click2dial_crm -#: field:res.users,context_propose_creation_crm_call:0 -msgid "Propose to create a call in CRM after a click2dial" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_reformat_all_phonenumbers -msgid "Reformat all phone numbers" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_res_users -msgid "Users" -msgstr "" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "Yes" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_phone_common -msgid "phone.common" -msgstr "" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_wizard_create_crm_phonecall -msgid "wizard.create.crm.phonecall" -msgstr "" - diff --git a/asterisk_click2dial_crm/i18n/ca.po b/asterisk_click2dial_crm/i18n/ca.po deleted file mode 100644 index b50b2d9..0000000 --- a/asterisk_click2dial_crm/i18n/ca.po +++ /dev/null @@ -1,44 +0,0 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * asterisk_click2dial_crm -# -msgid "" -msgstr "" -"Project-Id-Version: OpenERP Server 6.0.2\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2011-11-09 15:28+0000\n" -"PO-Revision-Date: 2011-11-09 16:30+0100\n" -"Last-Translator: Jesús Martín \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_res_partner_address -msgid "Partner Addresses" -msgstr "Adreça de l'empresa" - -#. module: asterisk_click2dial_crm -#: model:ir.module.module,description:asterisk_click2dial_crm.module_meta_information -msgid "" -"\n" -" Create a outbound phone call when the user makes a call phone by clicking\n" -" the click2dial button of the partner address view, and opens it in a new tab.\n" -" " -msgstr "" -"\n" -" Crea una trucada de telèfon sortint quan l'usuari fa una trucada de telèfon\n" -" mitjançant el botó click2dial de la vista d'adreces de l'empresa i l'obre a una\n" -" nova pestanya.\n" -" " - -#. module: asterisk_click2dial_crm -#: model:ir.module.module,shortdesc:asterisk_click2dial_crm.module_meta_information -msgid "Asterisk Click2dial CRM" -msgstr "Asterisk Click2dial CRM" - -#~ msgid "Reconciliation" -#~ msgstr "Reconciliació" - diff --git a/asterisk_click2dial_crm/i18n/es.po b/asterisk_click2dial_crm/i18n/es.po deleted file mode 100644 index a91196e..0000000 --- a/asterisk_click2dial_crm/i18n/es.po +++ /dev/null @@ -1,44 +0,0 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * asterisk_click2dial_crm -# -msgid "" -msgstr "" -"Project-Id-Version: OpenERP Server 6.0.2\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2011-11-09 15:28+0000\n" -"PO-Revision-Date: 2011-11-09 16:32+0100\n" -"Last-Translator: Jesús Martín \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_res_partner_address -msgid "Partner Addresses" -msgstr "Dirección de la empresa" - -#. module: asterisk_click2dial_crm -#: model:ir.module.module,description:asterisk_click2dial_crm.module_meta_information -msgid "" -"\n" -" Create a outbound phone call when the user makes a call phone by clicking\n" -" the click2dial button of the partner address view, and opens it in a new tab.\n" -" " -msgstr "" -"\n" -" Crea una llamada de teléfono saliente cuando el usuario hace una llamada de\n" -" teléfono mediante el botón click2dial de la vista de direcciones de la empresa y\n" -" la abre a una nueva pestaña.\n" -" " - -#. module: asterisk_click2dial_crm -#: model:ir.module.module,shortdesc:asterisk_click2dial_crm.module_meta_information -msgid "Asterisk Click2dial CRM" -msgstr "Asterisk Click2dial CRM" - -#~ msgid "Reconciliation" -#~ msgstr "Reconciliació" - diff --git a/asterisk_click2dial_crm/i18n/fr.po b/asterisk_click2dial_crm/i18n/fr.po deleted file mode 100644 index ba58f45..0000000 --- a/asterisk_click2dial_crm/i18n/fr.po +++ /dev/null @@ -1,88 +0,0 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * asterisk_click2dial_crm -# -msgid "" -msgstr "" -"Project-Id-Version: OpenERP Server 7.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-08-25 22:02+0000\n" -"PO-Revision-Date: 2014-08-25 22:02+0000\n" -"Last-Translator: Alexis de Lattre \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "CRM phone call" -msgstr "Appel dans la CRM" - -#. module: asterisk_click2dial_crm -#: model:ir.actions.act_window,name:asterisk_click2dial_crm.action_create_crm_phonecall -msgid "Create CRM phonecall" -msgstr "Créer un appel dans la CRM" - -#. module: asterisk_click2dial_crm -#: code:addons/asterisk_click2dial_crm/asterisk_click2dial_crm.py:46 -#, python-format -msgid "Create Call in CRM" -msgstr "Créer Appel dans CRM" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "Create a phone call in the CRM ?" -msgstr "Créer un appel téléphonique dans la CRM ?" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_crm_lead -msgid "Lead/Opportunity" -msgstr "Piste/opportunité" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "No" -msgstr "Non" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_wizard_open_calling_partner -msgid "Open calling partner" -msgstr "Ouvrir le partenaire appelant" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_res_partner -msgid "Partner" -msgstr "Partenaire" - -#. module: asterisk_click2dial_crm -#: field:res.users,context_propose_creation_crm_call:0 -msgid "Propose to create a call in CRM after a click2dial" -msgstr "Propose de créer un appel dans la CRM après un click2dial" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_reformat_all_phonenumbers -msgid "Reformat all phone numbers" -msgstr "Reformate tous les numéros de téléphone" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_res_users -msgid "Users" -msgstr "Utilisateurs" - -#. module: asterisk_click2dial_crm -#: view:wizard.create.crm.phonecall:0 -msgid "Yes" -msgstr "Oui" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_phone_common -msgid "phone.common" -msgstr "phone.common" - -#. module: asterisk_click2dial_crm -#: model:ir.model,name:asterisk_click2dial_crm.model_wizard_create_crm_phonecall -msgid "wizard.create.crm.phonecall" -msgstr "wizard.create.crm.phonecall" - diff --git a/asterisk_click2dial_crm/res_users_view.xml b/asterisk_click2dial_crm/res_users_view.xml deleted file mode 100644 index 0c57f29..0000000 --- a/asterisk_click2dial_crm/res_users_view.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - asterisk.crm.preferences.option.view - res.users - - - - 0 - - - - - - diff --git a/asterisk_click2dial_crm/static/description/icon.png b/asterisk_click2dial_crm/static/description/icon.png deleted file mode 100644 index f6a53a3be0dc6bf7453ea2a573eb53aa6d5eb1b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16778 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 xoSU0dv$L}Y55~vGyEDadghu0O*6LoKKLL diff --git a/base_phone/wizard/number_not_found.py b/base_phone/wizard/number_not_found.py index 3580c47..4fc4a5b 100644 --- a/base_phone/wizard/number_not_found.py +++ b/base_phone/wizard/number_not_found.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Asterisk Click2dial module for OpenERP -# Copyright (C) 2010-2013 Alexis de Lattre +# Base Phone module for Odoo +# Copyright (C) 2010-2015 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 @@ -35,7 +35,8 @@ class number_not_found(orm.TransientModel): 'calling_number': fields.char( 'Calling Number', size=64, readonly=True, help="Phone number of calling party that has been obtained " - "from Asterisk, in the format used by Asterisk (not E.164)."), + "from the telephony server, in the format used by the " + "telephony server (not E.164)."), 'e164_number': fields.char( 'E.164 Number', size=64, help="E.164 equivalent of the calling number."), diff --git a/base_phone/wizard/number_not_found_view.xml b/base_phone/wizard/number_not_found_view.xml index 1cd47e1..f88b49f 100644 --- a/base_phone/wizard/number_not_found_view.xml +++ b/base_phone/wizard/number_not_found_view.xml @@ -1,7 +1,6 @@ diff --git a/crm_phone/crm_phone.py b/crm_phone/crm_phone.py index 3558fb7..aa6751a 100644 --- a/crm_phone/crm_phone.py +++ b/crm_phone/crm_phone.py @@ -20,7 +20,7 @@ # ############################################################################## -from openerp import models, fields +from openerp import models, fields, api, _ class CrmLead(models.Model): @@ -95,3 +95,20 @@ class ResUsers(models.Model): context_propose_creation_crm_call = fields.Boolean( string='Propose to create a call in CRM after a click2dial', default=True) + + +class PhoneCommon(models.AbstractModel): + _inherit = 'phone.common' + + @api.model + def click2dial(self, erp_number): + res = super(PhoneCommon, self).click2dial(erp_number) + if ( + self.env.user.context_propose_creation_crm_call and + self.env.context.get('click2dial_model') + in ('res.partner', 'crm.lead')): + res.update({ + 'action_name': _('Create Call in CRM'), + 'action_model': 'wizard.create.crm.phonecall', + }) + return res diff --git a/crm_phone/res_users_view.xml b/crm_phone/res_users_view.xml index 75589dc..10ffaf9 100644 --- a/crm_phone/res_users_view.xml +++ b/crm_phone/res_users_view.xml @@ -10,7 +10,7 @@ - asterisk.crm.res.users.form + crm.phone.res.users.form res.users @@ -22,7 +22,7 @@ - asterisk.crm.preferences.option.view + crm.phone.preferences.option.view res.users diff --git a/crm_phone/wizard/number_not_found.py b/crm_phone/wizard/number_not_found.py index 26a1922..df48bb2 100644 --- a/crm_phone/wizard/number_not_found.py +++ b/crm_phone/wizard/number_not_found.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Asterisk Click2dial module for OpenERP -# Copyright (C) 2010-2013 Alexis de Lattre +# CRM Phone module for Odoo +# Copyright (C) 2010-2015 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 diff --git a/ovh_telephony_connector/__init__.py b/ovh_telephony_connector/__init__.py new file mode 100644 index 0000000..5bd76f3 --- /dev/null +++ b/ovh_telephony_connector/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OVH Connector module for Odoo +# Copyright (C) 2015 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 ovh_connector diff --git a/ovh_telephony_connector/__openerp__.py b/ovh_telephony_connector/__openerp__.py new file mode 100644 index 0000000..3493565 --- /dev/null +++ b/ovh_telephony_connector/__openerp__.py @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OVH Connector module for Odoo +# Copyright (C) 2015 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 . +# +############################################################################## + +{ + 'name': 'OVH Telephony Connector', + 'version': '0.1', + 'category': 'Phone', + 'license': 'AGPL-3', + 'summary': 'OVH-Odoo telephony connector (click2call)', + 'author': 'Akretion', + 'website': 'http://www.akretion.com/', + 'depends': ['base_phone'], + 'external_dependencies': {'python': ['phonenumbers', 'SOAPpy']}, + 'data': [ + 'res_users_view.xml', + ], + 'demo': [], + 'qweb': ['static/src/xml/*.xml'], + 'application': True, + 'installable': True, +} diff --git a/ovh_telephony_connector/ovh_connector.py b/ovh_telephony_connector/ovh_connector.py new file mode 100644 index 0000000..ef138e1 --- /dev/null +++ b/ovh_telephony_connector/ovh_connector.py @@ -0,0 +1,104 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OVH connector module for Odoo +# Copyright (C) 2015 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 import models, fields, api, _ +from openerp.exceptions import Warning +import logging + +try: + # -> pip install SOAPpy + from SOAPpy import WSDL +except ImportError: + WSDL = None + +_logger = logging.getLogger(__name__) + + +class ResUsers(models.Model): + _inherit = "res.users" + + ovh_billing_number = fields.Char(string='OVH Billing Number') + ovh_calling_number = fields.Char( + string="OVH Calling Number", help="The phone number that will " + "be presented during a click2dial") + ovh_click2call_login = fields.Char(string='OVH Click2call Login') + ovh_click2call_password = fields.Char( + string="OVH Click2call Password") + + +class PhoneCommon(models.AbstractModel): + _inherit = 'phone.common' + + @api.model + def click2dial(self, erp_number): + res = super(PhoneCommon, self).click2dial(erp_number) + if not erp_number: + raise Warning( + _('Missing phone number')) + + user = self.env.user + if not user.ovh_billing_number: + raise Warning( + _('Missing OVH Billing Number on user %s') % user.name) + + if not user.ovh_calling_number: + raise Warning( + _('Missing OVH Calling Number on user %s') % user.name) + + if not user.ovh_click2call_login: + raise Warning( + _('Missing OVH Click2call Login on user %s') % user.name) + + if not user.ovh_click2call_password: + raise Warning( + _('Missing OVH Click2dial Password on user %s') % user.name) + + soap = WSDL.Proxy('https://www.ovh.com/soapi/soapi-re-1.63.wsdl') + + called_number = self.convert_to_dial_number(erp_number) + _logger.debug( + 'Starting OVH telephonyClick2CallDo request with ' + 'login = %s billing number = %s calling number = %s ' + 'and called_number = %s' + % (user.ovh_click2call_login, user.ovh_billing_number, + user.ovh_calling_number, called_number)) + + try: + soap.telephonyClick2CallDo( + user.ovh_click2call_login, + user.ovh_click2call_password, + user.ovh_calling_number, + called_number, + user.ovh_billing_number) + _logger.info("OVH telephonyClick2CallDo successfull") + + except Exception, e: + _logger.error( + "Error in the OVH telephonyClick2CallDo request") + _logger.error( + "Here are the details of the error: '%s'" % unicode(e)) + raise Warning( + _("Click to call to OVH failed.\nHere is the error: " + "'%s'") + % unicode(e)) + + res['dialed_number'] = called_number + return res diff --git a/ovh_telephony_connector/res_users_view.xml b/ovh_telephony_connector/res_users_view.xml new file mode 100644 index 0000000..17c46bc --- /dev/null +++ b/ovh_telephony_connector/res_users_view.xml @@ -0,0 +1,42 @@ + + + + + + + + ovh_connector.res.users.form + res.users + + + + 0 + + + + + + + + + + + + + + ovh_connector.users.preferences.option.view + res.users + + + + 0 + + + + + + diff --git a/ovh_telephony_connector/static/src/xml/ovh_connector.xml b/ovh_telephony_connector/static/src/xml/ovh_connector.xml new file mode 100644 index 0000000..d469b31 --- /dev/null +++ b/ovh_telephony_connector/static/src/xml/ovh_connector.xml @@ -0,0 +1,17 @@ + + + + From b3cec69bcdf7484e48e6c405e61e333f98fdf1e3 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 21 May 2015 13:28:24 +0200 Subject: [PATCH 2/2] Add SOAPpy for travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d1662f9..a66e27c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ install: - git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} - travis_install_nightly - - pip install phonenumbers py-Asterisk + - pip install phonenumbers py-Asterisk SOAPpy - hg clone http://bitbucket.org/anybox/web_action_request -b ${VERSION} ${HOME}/web_action_request - hg clone http://bitbucket.org/anybox/bus_enhanced ${HOME}/bus_enhanced