diff --git a/asterisk_click2dial/__openerp__.py b/asterisk_click2dial/__openerp__.py index 427aae4..bac6600 100644 --- a/asterisk_click2dial/__openerp__.py +++ b/asterisk_click2dial/__openerp__.py @@ -2,7 +2,7 @@ ############################################################################## # # Asterisk Click2dial module for OpenERP -# Copyright (C) 2010-2013 Alexis de Lattre +# 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 @@ -51,22 +51,16 @@ It is possible to get a pop-up of the partner corresponding to the calling party A detailed documentation for this module is available on the Akretion Web site : http://www.akretion.com/en/products-and-services/openerp-asterisk-voip-connector """, 'author': 'Akretion', 'website': 'http://www.akretion.com/', - 'depends': ['base'], + 'depends': ['base_phone'], 'external_dependencies': {'python': ['phonenumbers', 'Asterisk']}, 'data': [ 'asterisk_server_view.xml', 'res_users_view.xml', 'res_partner_view.xml', 'wizard/open_calling_partner_view.xml', - 'wizard/reformat_all_phonenumbers_view.xml', 'security/asterisk_server_security.xml', 'security/ir.model.access.csv', ], - 'js': [ - 'static/src/js/*.js', - 'static/lib/js/*.js', - ], - 'qweb': ['static/src/xml/*.xml'], 'demo': ['asterisk_click2dial_demo.xml'], 'images': [ 'images/sshot-click2dial.jpg', @@ -76,4 +70,3 @@ A detailed documentation for this module is available on the Akretion Web site : 'installable': True, 'active': False, } - diff --git a/asterisk_click2dial/asterisk_click2dial.py b/asterisk_click2dial/asterisk_click2dial.py index 35b7e2a..9d4731a 100644 --- a/asterisk_click2dial/asterisk_click2dial.py +++ b/asterisk_click2dial/asterisk_click2dial.py @@ -377,8 +377,8 @@ class res_users(orm.Model): ] -class asterisk_common(orm.AbstractModel): - _name = 'asterisk.common' +class phone_common(orm.AbstractModel): + _inherit = 'phone.common' def action_dial(self, cr, uid, ids, context=None): '''Read the number to dial and call _connect_to_asterisk the right way''' @@ -396,69 +396,9 @@ class asterisk_common(orm.AbstractModel): return self.pool['asterisk.server']._dial_with_asterisk(cr, uid, erp_number_e164, context=context) - def generic_phonenumber_to_e164(self, cr, uid, ids, field_from_to_seq, context=None): - result = {} - from_field_seq = [item[0] for item in field_from_to_seq] - for record in self.read(cr, uid, ids, from_field_seq, context=context): - result[record['id']] = {} - for fromfield, tofield in field_from_to_seq: - if not record.get(fromfield): - res = False - else: - try: - res = phonenumbers.format_number(phonenumbers.parse(record.get(fromfield), None), phonenumbers.PhoneNumberFormat.E164) - except Exception, e: - _logger.error("Cannot reformat the phone number '%s' to E.164 format. Error message: %s" % (record.get(fromfield), e)) - _logger.error("You should fix this number and run the wizard 'Reformat all phone numbers' from the menu Settings > Configuration > Asterisk") - # If I raise an exception here, it won't be possible to install - # the module on a DB with bad phone numbers - #raise orm.except_orm(_('Error :'), _("Cannot reformat the phone number '%s' to E.164 format. Error message: %s" % (record.get(fromfield), e))) - res = False - result[record['id']][tofield] = res - #print "RESULT generic_phonenumber_to_e164", result - return result - - def _generic_reformat_phonenumbers(self, cr, uid, vals, phonefields=['phone', 'partner_phone', 'fax', 'mobile'], context=None): - """Reformat phone numbers in E.164 format i.e. +33141981242""" - if any([vals.get(field) for field in phonefields]): - user = self.pool['res.users'].browse(cr, uid, uid, context=context) - # country_id on res.company is a fields.function that looks at - # company_id.partner_id.addres(default).country_id - if user.company_id.country_id: - user_countrycode = user.company_id.country_id.code - else: - # We need to raise an exception here because, if we pass None as second arg of phonenumbers.parse(), it will raise an exception when you try to enter a phone number in national format... so it's better to raise the exception here - raise orm.except_orm(_('Error :'), _("You should set a country on the company '%s'" % user.company_id.name)) - #print "user_countrycode=", user_countrycode - for field in phonefields: - if vals.get(field): - init_value = vals.get(field) - try: - res_parse = phonenumbers.parse(vals.get(field), user_countrycode) - except Exception, e: - raise orm.except_orm(_('Error :'), _("Cannot reformat the phone number '%s' to international format. Error message: %s" % (vals.get(field), e))) - #print "res_parse=", res_parse - vals[field] = phonenumbers.format_number(res_parse, phonenumbers.PhoneNumberFormat.E164) - if init_value != vals[field]: - _logger.info("%s initial value: '%s' updated value: '%s'" % (field, init_value, vals[field])) - return vals - - - class res_partner(orm.Model): _name = 'res.partner' - _inherit = ['res.partner', 'asterisk.common'] - - - def create(self, cr, uid, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(res_partner, self).create(cr, uid, vals_reformated, context=context) - - - def write(self, cr, uid, ids, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(res_partner, self).write(cr, uid, ids, vals_reformated, context=context) - + _inherit = ['res.partner', 'phone.common'] def get_name_from_phone_number(self, cr, uid, number, context=None): '''Function to get name from phone number. Usefull for use from Asterisk diff --git a/asterisk_click2dial/asterisk_server_view.xml b/asterisk_click2dial/asterisk_server_view.xml index b735d37..0bcc1af 100644 --- a/asterisk_click2dial/asterisk_server_view.xml +++ b/asterisk_click2dial/asterisk_server_view.xml @@ -1,7 +1,7 @@ @@ -14,8 +14,8 @@ res.company - - + + @@ -74,7 +74,7 @@ asterisk.server.tree asterisk.server - + @@ -86,16 +86,15 @@ - Asterisk servers + Asterisk Servers asterisk.server form tree,form {'asterisk_server_main_view': True} - - - + + diff --git a/asterisk_click2dial/res_partner_view.xml b/asterisk_click2dial/res_partner_view.xml index 45ebcb3..142ab07 100644 --- a/asterisk_click2dial/res_partner_view.xml +++ b/asterisk_click2dial/res_partner_view.xml @@ -15,7 +15,7 @@ asterisk.res.partner.simplified.form.dial res.partner 15 - + @@ -36,7 +36,7 @@ asterisk.res.partner.form.dial res.partner 15 - + diff --git a/asterisk_click2dial/wizard/__init__.py b/asterisk_click2dial/wizard/__init__.py index 6416716..92ca19b 100644 --- a/asterisk_click2dial/wizard/__init__.py +++ b/asterisk_click2dial/wizard/__init__.py @@ -2,7 +2,7 @@ ############################################################################## # # Asterisk Click2Dial module for OpenERP -# Copyright (C) 2012-2013 Alexis de Lattre +# Copyright (C) 2012-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 @@ -19,5 +19,4 @@ # ############################################################################## -from . import reformat_all_phonenumbers from . import open_calling_partner diff --git a/asterisk_click2dial/wizard/reformat_all_phonenumbers.py b/asterisk_click2dial/wizard/reformat_all_phonenumbers.py deleted file mode 100644 index f009255..0000000 --- a/asterisk_click2dial/wizard/reformat_all_phonenumbers.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Asterisk Click2dial module for OpenERP -# Copyright (C) 2012-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 orm, fields -from openerp.tools.translate import _ -import logging - -_logger = logging.getLogger(__name__) - -class reformat_all_phonenumbers(orm.TransientModel): - _name = "reformat.all.phonenumbers" - _description = "Reformat all phone numbers" - - _columns = { - 'phonenumbers_not_reformatted': fields.text("Phone numbers that couldn't be reformatted"), - } - - - def _extend_reformat_phonenumbers(self, cr, uid, context=None): - '''This function is designed to be inherited - to extend the functionnality to objects other than res.partner''' - res = { - self.pool['res.partner']: { - 'allids': self.pool['res.partner'].search(cr, uid, ['|', ('active', '=', True), ('active', '=', False)], context=context), - 'phonefields': ['phone', 'fax', 'mobile'], - 'namefield': 'name', - } - } - return res - - def run_reformat_all_phonenumbers(self, cr, uid, ids, context=None): - _logger.info('Starting to reformat all the phone numbers') - phonenumbers_not_reformatted = '' - toreformat_dict = self._extend_reformat_phonenumbers(cr, uid, context=context) - for obj, prop in toreformat_dict.items(): - for entry in obj.read(cr, uid, prop['allids'], [prop['namefield']] + prop['phonefields'], context=context): - init_entry = entry.copy() - # entry is _updated_ by the fonction _generic_reformat_phonenumbers() - try: - obj._generic_reformat_phonenumbers(cr, uid, entry, context=context) - except Exception, e: - #raise orm.except_orm(_('Error :'), _("Problem on entry '%s'. Error message: %s" % (init_entry.get(prop['namefield']), e[1]))) - phonenumbers_not_reformatted += "Problem on %s '%s'. Error message: %s" % (obj._description, init_entry.get(prop['namefield']), e[1]) + "\n" - _logger.warning("Problem on %s '%s'. Error message: %s" % (obj._description, init_entry.get(prop['namefield']), e[1])) - continue - if any([init_entry.get(field) != entry.get(field) for field in prop['phonefields']]): - entry.pop('id') - entry.pop(prop['namefield']) - _logger.info('[%s] Reformating phone number: FROM %s TO %s' % (obj._description, unicode(init_entry), unicode(entry))) - obj.write(cr, uid, init_entry['id'], entry, context=context) - if not phonenumbers_not_reformatted: - phonenumbers_not_reformatted = 'All phone numbers have been reformatted successfully.' - self.write(cr, uid, ids[0], {'phonenumbers_not_reformatted': phonenumbers_not_reformatted}, context=context) - _logger.info('End of the phone number reformatting wizard') - return True diff --git a/asterisk_click2dial_crm/__openerp__.py b/asterisk_click2dial_crm/__openerp__.py index 9c1be90..87a3e90 100644 --- a/asterisk_click2dial_crm/__openerp__.py +++ b/asterisk_click2dial_crm/__openerp__.py @@ -3,13 +3,13 @@ # # Asterisk click2dial CRM module for OpenERP # Copyright (c) 2011 Zikzakmedia S.L. (http://zikzakmedia.com) -# Copyright (c) 2012-2013 Akretion (http://www.akretion.com) +# Copyright (c) 2012-2014 Akretion (http://www.akretion.com) # @author: Jesús Martín # @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 +# 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, @@ -27,28 +27,24 @@ "version": "0.1", "author": "Zikzakmedia SL, Akretion", "website": "http://www.zikzakmedia.com", - "license" : "AGPL-3", + "license": "AGPL-3", "category": "Customer Relationship Management", "description": """ - This module adds CRM-specific features to the asterisk_click2dial module. +Asterisk Click2dial CRM +======================= - It adds 2 features : +This module adds CRM-specific features to the asterisk_click2dial module. - 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. +It adds 2 features : - 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. +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. - This module has been initially developped by Zikzakmedia and has been enhanced by Akretion. +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. - A detailed documentation for the OpenERP-Asterisk connector is available on the Akretion Web site : http://www.akretion.com/en/products-and-services/openerp-asterisk-voip-connector - """, +This module has been initially developped by Zikzakmedia and has been enhanced by Akretion. + +A detailed documentation for the OpenERP-Asterisk connector is available on the Akretion Web site : http://www.akretion.com/en/products-and-services/openerp-asterisk-voip-connector +""", "depends": [ 'asterisk_click2dial', 'crm', diff --git a/asterisk_click2dial_crm/asterisk_click2dial_crm.py b/asterisk_click2dial_crm/asterisk_click2dial_crm.py index 2eb5060..e531956 100644 --- a/asterisk_click2dial_crm/asterisk_click2dial_crm.py +++ b/asterisk_click2dial_crm/asterisk_click2dial_crm.py @@ -3,14 +3,14 @@ # # Asterisk click2dial CRM module for OpenERP # Copyright (c) 2011 Zikzakmedia S.L. (http://zikzakmedia.com) -# Copyright (c) 2012-2013 Akretion (http://www.akretion.com) +# Copyright (c) 2012-2014 Akretion (http://www.akretion.com) # Copyright (C) 2013 Invitu # @author: Jesús Martín # @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 +# 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, @@ -24,12 +24,11 @@ ############################################################################## from openerp.osv import orm, fields -from openerp.tools.translate import _ class res_partner(orm.Model): _name = 'res.partner' - _inherit = ['res.partner', 'asterisk.common'] + _inherit = ['res.partner', 'phone.common'] def action_dial(self, cr, uid, ids, context=None): ''' @@ -58,7 +57,6 @@ class res_partner(orm.Model): return True - class res_users(orm.Model): _inherit = "res.users" @@ -66,24 +64,27 @@ class res_users(orm.Model): # Field name starts with 'context_' to allow modification by the user # in his preferences, cf server-61/openerp/addons/base/res/res_users.py # line 377 in "def write" of "class users" - 'context_propose_creation_crm_call': fields.boolean('Propose to create a call in CRM after a click2dial'), + 'context_propose_creation_crm_call': fields.boolean( + 'Propose to create a call in CRM after a click2dial'), } _defaults = { 'context_propose_creation_crm_call': True, } + class crm_lead(orm.Model): _name = 'crm.lead' - _inherit = ['crm.lead', 'asterisk.common'] - + _inherit = ['crm.lead', 'phone.common'] def create(self, cr, uid, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(crm_lead, self).create(cr, uid, vals_reformated, context=context) - + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(crm_lead, self).create( + cr, uid, vals_reformated, context=context) def write(self, cr, uid, ids, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(crm_lead, self).write(cr, uid, ids, vals_reformated, context=context) - + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(crm_lead, self).write( + cr, uid, ids, vals_reformated, context=context) diff --git a/asterisk_click2dial_crm/wizard/__init__.py b/asterisk_click2dial_crm/wizard/__init__.py index 5773113..aee3787 100644 --- a/asterisk_click2dial_crm/wizard/__init__.py +++ b/asterisk_click2dial_crm/wizard/__init__.py @@ -2,12 +2,12 @@ ############################################################################## # # Asterisk click2dial CRM module for OpenERP -# Copyright (c) 2012 Akretion (http://www.akretion.com/) +# 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 +# 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, diff --git a/asterisk_click2dial_crm/wizard/create_crm_phonecall.py b/asterisk_click2dial_crm/wizard/create_crm_phonecall.py index d2935f8..a5f05d8 100644 --- a/asterisk_click2dial_crm/wizard/create_crm_phonecall.py +++ b/asterisk_click2dial_crm/wizard/create_crm_phonecall.py @@ -3,13 +3,13 @@ # # Asterisk click2dial CRM module for OpenERP # Copyright (c) 2011 Zikzakmedia S.L. (http://zikzakmedia.com) -# Copyright (c) 2012-2013 Akretion (http://www.akretion.com) +# Copyright (c) 2012-2014 Akretion (http://www.akretion.com) # @author: Jesús Martín # @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 +# 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, @@ -22,28 +22,33 @@ # ############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ +from openerp.osv import orm class wizard_create_crm_phonecall(orm.TransientModel): _name = "wizard.create.crm.phonecall" def button_create_outgoing_phonecall(self, cr, uid, ids, context=None): - partner = self.pool['res.partner'].browse(cr, uid, context.get('partner_id'), context=context) - return self._create_open_crm_phonecall(cr, uid, partner, crm_categ='Outbound', context=context) + partner = self.pool['res.partner'].browse( + cr, uid, context.get('partner_id'), context=context) + return self._create_open_crm_phonecall( + cr, uid, partner, crm_categ='Outbound', context=context) - def _create_open_crm_phonecall(self, cr, uid, partner, crm_categ, context=None): + def _create_open_crm_phonecall( + self, cr, uid, partner, crm_categ, context=None): if context is None: context = {} - categ_ids = self.pool['crm.case.categ'].search(cr, uid, [('name','=',crm_categ)], context={'lang': 'en_US'}) - case_section_ids = self.pool['crm.case.section'].search(cr, uid, [('member_ids', 'in', uid)], context=context) + categ_ids = self.pool['crm.case.categ'].search( + cr, uid, [('name', '=', crm_categ)], context={'lang': 'en_US'}) + case_section_ids = self.pool['crm.case.section'].search( + cr, uid, [('member_ids', 'in', uid)], context=context) context.update({ 'default_partner_id': partner.id or False, 'default_partner_phone': partner.phone, 'default_partner_mobile': partner.mobile, 'default_categ_id': categ_ids and categ_ids[0] or False, - 'default_section_id': case_section_ids and case_section_ids[0] or False, + 'default_section_id': + case_section_ids and case_section_ids[0] or False, }) return { @@ -53,19 +58,19 @@ class wizard_create_crm_phonecall(orm.TransientModel): 'view_type': 'form', 'view_mode': 'form,tree', 'type': 'ir.actions.act_window', - 'nodestroy': False, # close the pop-up wizard after action + 'nodestroy': False, # close the pop-up wizard after action 'target': 'current', 'context': context, } - class wizard_open_calling_partner(orm.TransientModel): _inherit = "wizard.open.calling.partner" def create_incoming_phonecall(self, cr, uid, ids, crm_categ, context=None): '''Started by button on 'open calling partner wizard''' partner = self.browse(cr, uid, ids[0], context=context).partner_id - action = self.pool['wizard.create.crm.phonecall']._create_open_crm_phonecall(cr, uid, partner, crm_categ='Inbound', context=context) + action = self.pool['wizard.create.crm.phonecall'].\ + create_open_crm_phonecall( + cr, uid, partner, crm_categ='Inbound', context=context) return action - diff --git a/asterisk_click2dial_crm/wizard/reformat_all_phonenumbers.py b/asterisk_click2dial_crm/wizard/reformat_all_phonenumbers.py index f430576..4dd501f 100644 --- a/asterisk_click2dial_crm/wizard/reformat_all_phonenumbers.py +++ b/asterisk_click2dial_crm/wizard/reformat_all_phonenumbers.py @@ -2,12 +2,12 @@ ############################################################################## # # Asterisk click2dial CRM module for OpenERP -# Copyright (c) 2013 Akretion (http://www.akretion.com) +# Copyright (c) 2013-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 +# 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, @@ -27,9 +27,12 @@ class reformat_all_phonenumbers(orm.TransientModel): _inherit = "reformat.all.phonenumbers" def _extend_reformat_phonenumbers(self, cr, uid, context=None): - res = super(reformat_all_phonenumbers, self)._extend_reformat_phonenumbers(cr, uid, context=context) + res = super( + reformat_all_phonenumbers, self)._extend_reformat_phonenumbers( + cr, uid, context=context) res[self.pool['crm.lead']] = { - 'allids': self.pool['crm.lead'].search(cr, uid, [], context=context), + 'allids': self.pool['crm.lead'].search( + cr, uid, [], context=context), 'phonefields': ['phone', 'fax', 'mobile'], 'namefield': 'partner_name', } diff --git a/asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py b/asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py index 19db35a..dac0549 100644 --- a/asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py +++ b/asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py @@ -5,8 +5,8 @@ # Copyright (C) 2013 Invitu # # 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 +# 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, @@ -24,29 +24,36 @@ from openerp.osv import orm, fields class crm_claim(orm.Model): _name = 'crm.claim' - _inherit = ['crm.claim', 'asterisk.common'] - - - def format_phonenumber_to_e164(self, cr, uid, ids, name, arg, context=None): - return self.generic_phonenumber_to_e164(cr, uid, ids, [('partner_phone', 'partner_phone_e164')], context=context) + _inherit = ['crm.claim', 'phone.common'] + def format_phonenumber_to_e164( + self, cr, uid, ids, name, arg, context=None): + return self.generic_phonenumber_to_e164( + cr, uid, ids, [('partner_phone', 'partner_phone_e164')], + context=context) _columns = { # Note : even if we only have 1 field, we keep multi='..' - # because the generic function generic_phonenumber_to_e164() is designed - # to return the result as multi - 'partner_phone_e164': fields.function(format_phonenumber_to_e164, type='char', size=64, string='Phone in E.164 format', readonly=True, multi='e164claim', store={ - 'crm.claim': (lambda self, cr, uid, ids, c={}: ids, ['partner_phone'], 10), + # because the generic function generic_phonenumber_to_e164() is + # designed to return the result as multi + 'partner_phone_e164': fields.function( + format_phonenumber_to_e164, type='char', size=64, + string='Phone in E.164 format', readonly=True, multi='e164claim', + store={ + 'crm.claim': ( + lambda self, cr, uid, ids, c={}: ids, + ['partner_phone'], 10), }), } - def create(self, cr, uid, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(crm_claim, self).create(cr, uid, vals_reformated, context=context) - + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(crm_claim, self).create( + cr, uid, vals_reformated, context=context) def write(self, cr, uid, ids, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(crm_claim, self).write(cr, uid, ids, vals_reformated, context=context) - + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(crm_claim, self).write( + cr, uid, ids, vals_reformated, context=context) diff --git a/asterisk_click2dial_crm_claim/wizard/open_calling_partner.py b/asterisk_click2dial_crm_claim/wizard/open_calling_partner.py index 2981537..dd01a0a 100644 --- a/asterisk_click2dial_crm_claim/wizard/open_calling_partner.py +++ b/asterisk_click2dial_crm_claim/wizard/open_calling_partner.py @@ -2,7 +2,7 @@ ############################################################################## # # Asterisk Click2dial CRM Claim module for OpenERP -# Copyright (C) 2012-2013 Akretion (http://www.akretion.com/) +# 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 @@ -20,11 +20,13 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp.osv import orm + class wizard_open_calling_partner(orm.TransientModel): _inherit = "wizard.open.calling.partner" def open_crm_claims(self, cr, uid, ids, context=None): '''Function called by the related button of the wizard''' - return self.open_filtered_object(cr, uid, ids, self.pool.get('crm.claim'), context=context) + return self.open_filtered_object( + cr, uid, ids, self.pool.get('crm.claim'), context=context) diff --git a/asterisk_click2dial_crm_claim/wizard/reformat_all_phonenumbers.py b/asterisk_click2dial_crm_claim/wizard/reformat_all_phonenumbers.py index 8a49017..61e8ae8 100644 --- a/asterisk_click2dial_crm_claim/wizard/reformat_all_phonenumbers.py +++ b/asterisk_click2dial_crm_claim/wizard/reformat_all_phonenumbers.py @@ -2,12 +2,12 @@ ############################################################################## # # Asterisk click2dial CRM Claim module for OpenERP -# Copyright (c) 2013 Akretion (http://www.akretion.com) +# Copyright (c) 2013-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 +# 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, @@ -27,9 +27,12 @@ class reformat_all_phonenumbers(orm.TransientModel): _inherit = "reformat.all.phonenumbers" def _extend_reformat_phonenumbers(self, cr, uid, context=None): - res = super(reformat_all_phonenumbers, self)._extend_reformat_phonenumbers(cr, uid, context=context) + res = super( + reformat_all_phonenumbers, self)._extend_reformat_phonenumbers( + cr, uid, context=context) res[self.pool['crm.claim']] = { - 'allids': self.pool['crm.claim'].search(cr, uid, [], context=context), + 'allids': self.pool['crm.claim'].search( + cr, uid, [], context=context), 'phonefields': ['partner_phone'], 'namefield': 'name', } diff --git a/asterisk_click2dial_registration/__openerp__.py b/asterisk_click2dial_registration/__openerp__.py index bb442bb..b73dd4c 100644 --- a/asterisk_click2dial_registration/__openerp__.py +++ b/asterisk_click2dial_registration/__openerp__.py @@ -5,8 +5,8 @@ # Copyright (C) 2013 Invitu # # 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 +# 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, @@ -24,8 +24,8 @@ "version": "0.1", "author": "INVITU", "website": "http://www.invitu.com", - "license" : "AGPL-3", - "category": "", + "license": "AGPL-3", + "category": "Extra Tools", "description": """ This module adds a button "Open Registrations" on the "Open calling partner" wizard and a "Dial" button on the Registration form. diff --git a/asterisk_click2dial_registration/asterisk_click2dial_registration.py b/asterisk_click2dial_registration/asterisk_click2dial_registration.py index 6d3ad4a..8e6d4a1 100644 --- a/asterisk_click2dial_registration/asterisk_click2dial_registration.py +++ b/asterisk_click2dial_registration/asterisk_click2dial_registration.py @@ -5,8 +5,8 @@ # Copyright (C) 2013 Invitu # # 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 +# 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, @@ -19,20 +19,21 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp.osv import orm class event_registration(orm.Model): _name = 'event.registration' - _inherit = ['event.registration', 'asterisk.common'] - + _inherit = ['event.registration', 'phone.common'] def create(self, cr, uid, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(event_registration, self).create(cr, uid, vals_reformated, context=context) - + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(event_registration, self).create( + cr, uid, vals_reformated, context=context) def write(self, cr, uid, ids, vals, context=None): - vals_reformated = self._generic_reformat_phonenumbers(cr, uid, vals, context=context) - return super(event_registration, self).write(cr, uid, ids, vals_reformated, context=context) - + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(event_registration, self).write( + cr, uid, ids, vals_reformated, context=context) diff --git a/asterisk_click2dial_registration/wizard/open_calling_partner.py b/asterisk_click2dial_registration/wizard/open_calling_partner.py index d1dbc79..7a17dcb 100644 --- a/asterisk_click2dial_registration/wizard/open_calling_partner.py +++ b/asterisk_click2dial_registration/wizard/open_calling_partner.py @@ -21,9 +21,11 @@ from openerp.osv import orm + class wizard_open_calling_partner(orm.TransientModel): _inherit = "wizard.open.calling.partner" def open_registrations(self, cr, uid, ids, context=None): '''Function called by the related button of the wizard''' - return self.open_filtered_object(cr, uid, ids, self.pool.get('event.registration'), context=context) + return self.open_filtered_object( + cr, uid, ids, self.pool.get('event.registration'), context=context) diff --git a/base_phone/__init__.py b/base_phone/__init__.py new file mode 100644 index 0000000..f9be1f7 --- /dev/null +++ b/base_phone/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Base Module module for OpenERP +# Copyright (C) 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 . +# +############################################################################## + +from . import base_phone +from . import wizard diff --git a/base_phone/__openerp__.py b/base_phone/__openerp__.py new file mode 100644 index 0000000..4812efa --- /dev/null +++ b/base_phone/__openerp__.py @@ -0,0 +1,55 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Base Phone module for OpenERP +# Copyright (C) 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 . +# +############################################################################## + + +{ + 'name': 'Base Phone', + 'version': '0.1', + 'category': 'Extra Tools', + 'license': 'AGPL-3', + 'summary': 'Validate phone numbers', + 'description': """ +Base Phone +========== + +This module validate phone numbers using the phonenumbers Python library, which is a port of the lib used in Android smartphones. It also adds tel: links on phone numbers. + +This module is independant from the Asterisk connector. + +Please contact Alexis de Lattre from Akretion for any help or question about this module. +""", + 'author': 'Akretion', + 'website': 'http://www.akretion.com/', + 'depends': ['base'], + 'external_dependencies': {'python': ['phonenumbers']}, + 'data': [ + 'res_partner_view.xml', + 'wizard/reformat_all_phonenumbers_view.xml', + ], + 'js': [ + 'static/src/js/*.js', + 'static/lib/js/*.js', + ], + 'qweb': ['static/src/xml/*.xml'], + 'images': [], + 'installable': True, + 'active': False, +} diff --git a/base_phone/base_phone.py b/base_phone/base_phone.py new file mode 100644 index 0000000..25d373f --- /dev/null +++ b/base_phone/base_phone.py @@ -0,0 +1,120 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Base Phone 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 . +# +############################################################################## + +from openerp.osv import orm +from openerp.tools.translate import _ +import logging +# Lib for phone number reformating -> pip install phonenumbers +import phonenumbers + +_logger = logging.getLogger(__name__) + + +class phone_common(orm.AbstractModel): + _name = 'phone.common' + + def generic_phonenumber_to_e164( + self, cr, uid, ids, field_from_to_seq, context=None): + result = {} + from_field_seq = [item[0] for item in field_from_to_seq] + for record in self.read(cr, uid, ids, from_field_seq, context=context): + result[record['id']] = {} + for fromfield, tofield in field_from_to_seq: + if not record.get(fromfield): + res = False + else: + try: + res = phonenumbers.format_number( + phonenumbers.parse(record.get(fromfield), None), + phonenumbers.PhoneNumberFormat.E164) + except Exception, e: + _logger.error( + "Cannot reformat the phone number '%s' to E.164 " + "format. Error message: %s" + % (record.get(fromfield), e)) + _logger.error( + "You should fix this number and run the wizard " + "'Reformat all phone numbers' from the menu " + "Settings > Configuration > Phones") + # If I raise an exception here, it won't be possible to + # install the module on a DB with bad phone numbers + res = False + result[record['id']][tofield] = res + return result + + def _generic_reformat_phonenumbers( + self, cr, uid, vals, + phonefields=['phone', 'partner_phone', 'fax', 'mobile'], + context=None): + """Reformat phone numbers in E.164 format i.e. +33141981242""" + if any([vals.get(field) for field in phonefields]): + user = self.pool['res.users'].browse(cr, uid, uid, context=context) + # country_id on res.company is a fields.function that looks at + # company_id.partner_id.addres(default).country_id + if user.company_id.country_id: + user_countrycode = user.company_id.country_id.code + else: + # We need to raise an exception here because, if we pass None + # as second arg of phonenumbers.parse(), it will raise an + # exception when you try to enter a phone number in + # national format... so it's better to raise the exception here + raise orm.except_orm( + _('Error :'), + _("You should set a country on the company '%s'") + % user.company_id.name) + #print "user_countrycode=", user_countrycode + for field in phonefields: + if vals.get(field): + init_value = vals.get(field) + try: + res_parse = phonenumbers.parse( + vals.get(field), user_countrycode) + except Exception, e: + raise orm.except_orm( + _('Error :'), + _("Cannot reformat the phone number '%s' to " + "international format. Error message: %s") + % (vals.get(field), e)) + #print "res_parse=", res_parse + vals[field] = phonenumbers.format_number( + res_parse, phonenumbers.PhoneNumberFormat.E164) + if init_value != vals[field]: + _logger.info( + "%s initial value: '%s' updated value: '%s'" + % (field, init_value, vals[field])) + return vals + + +class res_partner(orm.Model): + _name = 'res.partner' + _inherit = ['res.partner', 'phone.common'] + + def create(self, cr, uid, vals, context=None): + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(res_partner, self).create( + cr, uid, vals_reformated, context=context) + + def write(self, cr, uid, ids, vals, context=None): + vals_reformated = self._generic_reformat_phonenumbers( + cr, uid, vals, context=context) + return super(res_partner, self).write( + cr, uid, ids, vals_reformated, context=context) diff --git a/base_phone/res_partner_view.xml b/base_phone/res_partner_view.xml new file mode 100644 index 0000000..f0a66f6 --- /dev/null +++ b/base_phone/res_partner_view.xml @@ -0,0 +1,50 @@ + + + + + + + + base.phone.res.partner.simplified.form + res.partner + + + + phone + + + phone + + + + + + base.phone.res.partner.form + res.partner + + + + phone + + + phone + + + fax + + + phone + + + phone + + + + + + + diff --git a/asterisk_click2dial/static/lib/js/PhoneFormat.js b/base_phone/static/lib/js/PhoneFormat.js similarity index 100% rename from asterisk_click2dial/static/lib/js/PhoneFormat.js rename to base_phone/static/lib/js/PhoneFormat.js diff --git a/asterisk_click2dial/static/src/js/phone_widget.js b/base_phone/static/src/js/phone_widget.js similarity index 77% rename from asterisk_click2dial/static/src/js/phone_widget.js rename to base_phone/static/src/js/phone_widget.js index f1cd920..0f7a4cd 100644 --- a/asterisk_click2dial/static/src/js/phone_widget.js +++ b/base_phone/static/src/js/phone_widget.js @@ -1,11 +1,11 @@ // Base phone module for OpenERP -// Copyright (C) 2013 Alexis de Lattre +// Copyright (C) 2013-2014 Alexis de Lattre // The licence is in the file __openerp__.py -openerp.asterisk_click2dial = function (instance) { +openerp.base_phone = function (instance) { - instance.asterisk_click2dial.FieldPhone = instance.web.form.FieldChar.extend({ + instance.base_phone.FieldPhone = instance.web.form.FieldChar.extend({ template: 'FieldPhone', initialize_content: function() { this._super(); @@ -28,9 +28,9 @@ openerp.asterisk_click2dial = function (instance) { } }); - instance.web.form.widgets.add('phone', 'instance.asterisk_click2dial.FieldPhone'); + instance.web.form.widgets.add('phone', 'instance.base_phone.FieldPhone'); - instance.asterisk_click2dial.FieldFax = instance.web.form.FieldChar.extend({ + instance.base_phone.FieldFax = instance.web.form.FieldChar.extend({ template: 'FieldFax', initialize_content: function() { this._super(); @@ -53,8 +53,6 @@ openerp.asterisk_click2dial = function (instance) { } }); - instance.web.form.widgets.add('fax', 'instance.asterisk_click2dial.FieldFax'); + instance.web.form.widgets.add('fax', 'instance.base_phone.FieldFax'); - - - } +} diff --git a/asterisk_click2dial/static/src/xml/phone.xml b/base_phone/static/src/xml/phone.xml similarity index 100% rename from asterisk_click2dial/static/src/xml/phone.xml rename to base_phone/static/src/xml/phone.xml diff --git a/base_phone/wizard/__init__.py b/base_phone/wizard/__init__.py new file mode 100644 index 0000000..718b0f5 --- /dev/null +++ b/base_phone/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Base Phone module for OpenERP +# Copyright (C) 2012-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 . +# +############################################################################## + +from . import reformat_all_phonenumbers diff --git a/base_phone/wizard/reformat_all_phonenumbers.py b/base_phone/wizard/reformat_all_phonenumbers.py new file mode 100644 index 0000000..2d19189 --- /dev/null +++ b/base_phone/wizard/reformat_all_phonenumbers.py @@ -0,0 +1,100 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# Base Phone module for OpenERP +# Copyright (C) 2012-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 . +# +############################################################################## + +from openerp.osv import orm, fields +import logging + +_logger = logging.getLogger(__name__) + + +class reformat_all_phonenumbers(orm.TransientModel): + _name = "reformat.all.phonenumbers" + _description = "Reformat all phone numbers" + + _columns = { + 'phonenumbers_not_reformatted': fields.text( + "Phone numbers that couldn't be reformatted"), + } + + def _extend_reformat_phonenumbers(self, cr, uid, context=None): + '''This function is designed to be inherited + to extend the functionnality to objects other than res.partner''' + res = { + self.pool['res.partner']: { + 'allids': self.pool['res.partner'].search( + cr, uid, [ + '|', + ('active', '=', True), + ('active', '=', False) + ], context=context), + 'phonefields': ['phone', 'fax', 'mobile'], + 'namefield': 'name', + } + } + return res + + def run_reformat_all_phonenumbers(self, cr, uid, ids, context=None): + _logger.info('Starting to reformat all the phone numbers') + phonenumbers_not_reformatted = '' + toreformat_dict = self._extend_reformat_phonenumbers( + cr, uid, context=context) + for obj, prop in toreformat_dict.items(): + for entry in obj.read( + cr, uid, prop['allids'], + [prop['namefield']] + prop['phonefields'], + context=context): + init_entry = entry.copy() + # entry is _updated_ by the fonction + # _generic_reformat_phonenumbers() + try: + obj._generic_reformat_phonenumbers( + cr, uid, entry, context=context) + except Exception, e: + phonenumbers_not_reformatted += \ + "Problem on %s '%s'. Error message: %s\n" % ( + obj._description, + init_entry.get(prop['namefield']), e[1]) + _logger.warning( + "Problem on %s '%s'. Error message: %s" % ( + obj._description, + init_entry.get(prop['namefield']), e[1])) + continue + if any( + [init_entry.get(field) + != entry.get(field) for field + in prop['phonefields']]): + entry.pop('id') + entry.pop(prop['namefield']) + _logger.info( + '[%s] Reformating phone number: FROM %s TO %s' % ( + obj._description, unicode(init_entry), + unicode(entry))) + obj.write( + cr, uid, init_entry['id'], entry, context=context) + if not phonenumbers_not_reformatted: + phonenumbers_not_reformatted = \ + 'All phone numbers have been reformatted successfully.' + self.write( + cr, uid, ids[0], + {'phonenumbers_not_reformatted': phonenumbers_not_reformatted}, + context=context) + _logger.info('End of the phone number reformatting wizard') + return True diff --git a/asterisk_click2dial/wizard/reformat_all_phonenumbers_view.xml b/base_phone/wizard/reformat_all_phonenumbers_view.xml similarity index 85% rename from asterisk_click2dial/wizard/reformat_all_phonenumbers_view.xml rename to base_phone/wizard/reformat_all_phonenumbers_view.xml index a4503e8..32dcc73 100644 --- a/asterisk_click2dial/wizard/reformat_all_phonenumbers_view.xml +++ b/base_phone/wizard/reformat_all_phonenumbers_view.xml @@ -1,6 +1,6 @@ @@ -30,15 +30,17 @@ - Reformat all phone numbers + Reformat Phone Numbers reformat.all.phonenumbers form form new - - + + + +