From 8d4c7fa99bafd101bc8d7793067392a05474bd95 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 12 Mar 2015 12:43:05 +0100 Subject: [PATCH 1/8] Add support for "Create CRM phonecall" on leads (and not only partners) Re-organise the codebase to prepare the arrival of a new module for a telephony system other than Asterisk --- asterisk_click2dial/asterisk_click2dial.py | 40 ++-------- asterisk_click2dial_crm/__init__.py | 1 - asterisk_click2dial_crm/__openerp__.py | 2 - .../asterisk_click2dial_crm.py | 35 ++------- asterisk_click2dial_crm/wizard/__init__.py | 23 ------ .../wizard/create_crm_phonecall.py | 61 --------------- base_phone/base_phone.py | 74 +++++++++++-------- base_phone/static/src/js/phone_widget.js | 10 +-- crm_phone/__openerp__.py | 2 + crm_phone/crm_phone.py | 31 +++++--- .../res_users_view.xml | 8 +- crm_phone/wizard/__init__.py | 1 + crm_phone/wizard/create_crm_phonecall.py | 73 ++++++++++++++++++ .../wizard/create_crm_phonecall_view.xml | 0 14 files changed, 165 insertions(+), 196 deletions(-) delete mode 100644 asterisk_click2dial_crm/wizard/__init__.py delete mode 100644 asterisk_click2dial_crm/wizard/create_crm_phonecall.py rename {asterisk_click2dial_crm => crm_phone}/res_users_view.xml (80%) create mode 100644 crm_phone/wizard/create_crm_phonecall.py rename {asterisk_click2dial_crm => crm_phone}/wizard/create_crm_phonecall_view.xml (100%) diff --git a/asterisk_click2dial/asterisk_click2dial.py b/asterisk_click2dial/asterisk_click2dial.py index 125f910..84f90ab 100644 --- a/asterisk_click2dial/asterisk_click2dial.py +++ b/asterisk_click2dial/asterisk_click2dial.py @@ -148,36 +148,6 @@ class asterisk_server(orm.Model): 'context', 'alert_info', 'login', 'password'] )] - def _reformat_number( - self, cr, uid, erp_number, ast_server=None, context=None): - ''' - This function is dedicated to the transformation of the number - available in OpenERP to the number that Asterisk should dial. - You may have to inherit this function in another module specific - for your company if you are not happy with the way I reformat - the OpenERP numbers. - ''' - assert(erp_number), 'Missing phone number' - _logger.debug('Number before reformat = %s' % erp_number) - if not ast_server: - ast_server = self._get_asterisk_server_from_user( - cr, uid, context=context) - - # erp_number are supposed to be in E.164 format, so no need to - # give a country code here - parsed_num = phonenumbers.parse(erp_number, None) - country_code = ast_server.company_id.country_id.code - assert(country_code), 'Missing country on company' - _logger.debug('Country code = %s' % country_code) - to_dial_number = phonenumbers.format_out_of_country_calling_number( - parsed_num, country_code.upper()).replace(' ', '').replace('-', '') - # Add 'out prefix' to all numbers - if ast_server.out_prefix: - _logger.debug('Out prefix = %s' % ast_server.out_prefix) - to_dial_number = '%s%s' % (ast_server.out_prefix, to_dial_number) - _logger.debug('Number to be sent to Asterisk = %s' % to_dial_number) - return to_dial_number - 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 @@ -429,15 +399,19 @@ class phone_common(orm.AbstractModel): def click2dial(self, cr, uid, erp_number, context=None): if not erp_number: - orm.except_orm( + raise orm.except_orm( _('Error:'), _('Missing phone number')) user, ast_server, ast_manager = \ self.pool['asterisk.server']._connect_to_asterisk( cr, uid, context=context) - ast_number = self.pool['asterisk.server']._reformat_number( - cr, uid, erp_number, ast_server, context=context) + 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) + ast_number = '%s%s' % (ast_server.out_prefix, ast_number) + _logger.debug('Number to be sent to Asterisk = %s' % ast_number) # The user should have a CallerID if not user.callerid: diff --git a/asterisk_click2dial_crm/__init__.py b/asterisk_click2dial_crm/__init__.py index c561ae1..a42e8f0 100644 --- a/asterisk_click2dial_crm/__init__.py +++ b/asterisk_click2dial_crm/__init__.py @@ -21,4 +21,3 @@ ############################################################################## from . import asterisk_click2dial_crm -from . import wizard diff --git a/asterisk_click2dial_crm/__openerp__.py b/asterisk_click2dial_crm/__openerp__.py index a46ac9e..1e3e3dc 100644 --- a/asterisk_click2dial_crm/__openerp__.py +++ b/asterisk_click2dial_crm/__openerp__.py @@ -56,9 +56,7 @@ http://www.akretion.com/products-and-services/openerp-asterisk-voip-connector 'asterisk_click2dial', 'crm_phone', ], - "demo": [], "data": [ - 'wizard/create_crm_phonecall_view.xml', 'res_users_view.xml', ], "installable": True, diff --git a/asterisk_click2dial_crm/asterisk_click2dial_crm.py b/asterisk_click2dial_crm/asterisk_click2dial_crm.py index a77cef3..50e3065 100644 --- a/asterisk_click2dial_crm/asterisk_click2dial_crm.py +++ b/asterisk_click2dial_crm/asterisk_click2dial_crm.py @@ -20,45 +20,26 @@ # ############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ +from openerp import models, api, _ -class phone_common(orm.AbstractModel): +class PhoneCommon(models.AbstractModel): _inherit = 'phone.common' - def click2dial(self, cr, uid, erp_number, context=None): + @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 ''' - if context is None: - context = {} - res = super(phone_common, self).click2dial( - cr, uid, erp_number, context=context) - user = self.pool['res.users'].browse(cr, uid, uid, context=context) + res = super(PhoneCommon, self).click2dial(erp_number) if ( - context.get('click2dial_model') == 'res.partner' - and user.context_propose_creation_crm_call): + 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 - - -class res_users(orm.Model): - _inherit = "res.users" - - _columns = { - # Field name starts with 'context_' to allow modification by the user - # in his preferences, cf server/openerp/addons/base/res/res_users.py - # in "def write()" of "class res_users(osv.osv)" - 'context_propose_creation_crm_call': fields.boolean( - 'Propose to create a call in CRM after a click2dial'), - } - - _defaults = { - 'context_propose_creation_crm_call': True, - } diff --git a/asterisk_click2dial_crm/wizard/__init__.py b/asterisk_click2dial_crm/wizard/__init__.py deleted file mode 100644 index 9f6c118..0000000 --- a/asterisk_click2dial_crm/wizard/__init__.py +++ /dev/null @@ -1,23 +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 . import create_crm_phonecall diff --git a/asterisk_click2dial_crm/wizard/create_crm_phonecall.py b/asterisk_click2dial_crm/wizard/create_crm_phonecall.py deleted file mode 100644 index d9b9578..0000000 --- a/asterisk_click2dial_crm/wizard/create_crm_phonecall.py +++ /dev/null @@ -1,61 +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.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) - - 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) - 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, - }) - - return { - 'name': partner.name, - 'domain': [('partner_id', '=', partner.id)], - 'res_model': 'crm.phonecall', - 'view_mode': 'form,tree', - 'type': 'ir.actions.act_window', - 'nodestroy': False, # close the pop-up wizard after action - 'target': 'current', - 'context': context, - } diff --git a/base_phone/base_phone.py b/base_phone/base_phone.py index 51a70ee..2131978 100644 --- a/base_phone/base_phone.py +++ b/base_phone/base_phone.py @@ -19,8 +19,8 @@ # ############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ +from openerp import models, fields, api, _ +from openerp.exceptions import Warning import logging # Lib for phone number reformating -> pip install phonenumbers import phonenumbers @@ -28,7 +28,7 @@ import phonenumbers _logger = logging.getLogger(__name__) -class phone_common(orm.AbstractModel): +class PhoneCommon(models.AbstractModel): _name = 'phone.common' def generic_phonenumber_to_e164( @@ -81,8 +81,7 @@ class phone_common(orm.AbstractModel): # 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:'), + raise Warning( _("You should set a country on the company '%s'") % user.company_id.name) for field in phonefields: @@ -107,8 +106,7 @@ class phone_common(orm.AbstractModel): "Cannot reformat the phone number '%s' to " "international format" % vals.get(field)) if context.get('raise_if_phone_parse_fails'): - raise orm.except_orm( - _('Error:'), + raise Warning( _("Cannot reformat the phone number '%s' to " "international format. Error message: %s") % (vals.get(field), e)) @@ -215,21 +213,44 @@ class phone_common(orm.AbstractModel): modules, such as asterisk_click2dial''' return {'dialed_number': erp_number} + @api.model + def convert_to_dial_number(self, erp_number): + ''' + This function is dedicated to the transformation of the number + available in Odoo to the number that can be dialed. + You may have to inherit this function in another module specific + for your company if you are not happy with the way I reformat + the numbers. + ''' + assert(erp_number), 'Missing phone number' + _logger.debug('Number before reformat = %s' % erp_number) + # erp_number are supposed to be in E.164 format, so no need to + # give a country code here + parsed_num = phonenumbers.parse(erp_number, None) + country_code = self.env.user.company_id.country_id.code + assert(country_code), 'Missing country on company' + _logger.debug('Country code = %s' % country_code) + to_dial_number = phonenumbers.format_out_of_country_calling_number( + parsed_num, country_code.upper()) + to_dial_number = str(to_dial_number).translate(None, ' -.()/') + _logger.debug('Number to be sent to Asterisk = %s' % to_dial_number) + return to_dial_number -class res_partner(orm.Model): + +class ResPartner(models.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( + return super(ResPartner, 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( + return super(ResPartner, self).write( cr, uid, ids, vals_reformated, context=context) def name_get(self, cr, uid, ids, context=None): @@ -247,30 +268,25 @@ class res_partner(orm.Model): res.append((partner.id, name)) return res else: - return super(res_partner, self).name_get( + return super(ResPartner, self).name_get( cr, uid, ids, context=context) -class res_company(orm.Model): +class ResCompany(models.Model): _inherit = 'res.company' - _columns = { - 'number_of_digits_to_match_from_end': fields.integer( - 'Number of Digits To Match From End', - help="In several situations, OpenERP will have to find a " - "Partner/Lead/Employee/... from a phone number presented by the " - "calling party. As the phone numbers presented by your phone " - "operator may not always be displayed in a standard format, " - "the best method to find the related Partner/Lead/Employee/... " - "in OpenERP is to try to match the end of the phone number in " - "OpenERP with the N last digits of the phone number presented " - "by the calling party. N is the value you should enter in this " - "field."), - } - - _defaults = { - 'number_of_digits_to_match_from_end': 8, - } + number_of_digits_to_match_from_end = fields.Integer( + string='Number of Digits To Match From End', + default=8, + help="In several situations, OpenERP will have to find a " + "Partner/Lead/Employee/... from a phone number presented by the " + "calling party. As the phone numbers presented by your phone " + "operator may not always be displayed in a standard format, " + "the best method to find the related Partner/Lead/Employee/... " + "in OpenERP is to try to match the end of the phone number in " + "OpenERP with the N last digits of the phone number presented " + "by the calling party. N is the value you should enter in this " + "field.") _sql_constraints = [( 'number_of_digits_to_match_from_end_positive', diff --git a/base_phone/static/src/js/phone_widget.js b/base_phone/static/src/js/phone_widget.js index 478a30f..5cbefa6 100644 --- a/base_phone/static/src/js/phone_widget.js +++ b/base_phone/static/src/js/phone_widget.js @@ -57,11 +57,11 @@ openerp.base_phone = function (instance) { _t('Click2dial successfull'), _t('Number dialed:') + ' ' + r.dialed_number); if (r.action_model) { - var context = {}; - if (self.view.dataset.model == 'res.partner') { - context = { - 'partner_id': self.view.datarecord.id}; - } + var context = { + 'click2dial_model': self.view.dataset.model, + 'click2dial_id': self.view.datarecord.id, + 'phone_number': phone_num, + }; var action = { name: r.action_name, type: 'ir.actions.act_window', diff --git a/crm_phone/__openerp__.py b/crm_phone/__openerp__.py index 6b9233b..f2978bf 100644 --- a/crm_phone/__openerp__.py +++ b/crm_phone/__openerp__.py @@ -45,7 +45,9 @@ for any help or question about this module. 'data': [ 'security/ir.model.access.csv', 'crm_view.xml', + 'res_users_view.xml', 'wizard/number_not_found_view.xml', + 'wizard/create_crm_phonecall_view.xml', ], 'images': [], 'installable': True, diff --git a/crm_phone/crm_phone.py b/crm_phone/crm_phone.py index 481dfb3..42e61b0 100644 --- a/crm_phone/crm_phone.py +++ b/crm_phone/crm_phone.py @@ -20,23 +20,23 @@ # ############################################################################## -from openerp.osv import orm +from openerp import models, fields -class crm_lead(orm.Model): +class CrmLead(models.Model): _name = 'crm.lead' _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( + return super(CrmLead, 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( + return super(CrmLead, self).write( cr, uid, ids, vals_reformated, context=context) def name_get(self, cr, uid, ids, context=None): @@ -58,32 +58,32 @@ class crm_lead(orm.Model): res.append((lead.id, name)) return res else: - return super(crm_lead, self).name_get( + return super(CrmLead, self).name_get( cr, uid, ids, context=context) -class crm_phonecall(orm.Model): +class CrmPhonecall(models.Model): _name = 'crm.phonecall' _inherit = ['crm.phonecall', 'phone.common'] def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( cr, uid, vals, context=context) - return super(crm_phonecall, self).create( + return super(CrmPhonecall, 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_phonecall, self).write( + return super(CrmPhonecall, self).write( cr, uid, ids, vals_reformated, context=context) -class phone_common(orm.AbstractModel): +class PhoneCommon(models.AbstractModel): _inherit = 'phone.common' def _get_phone_fields(self, cr, uid, context=None): - res = super(phone_common, self)._get_phone_fields( + res = super(PhoneCommon, self)._get_phone_fields( cr, uid, context=context) res.update({ 'crm.lead': { @@ -96,3 +96,14 @@ class phone_common(orm.AbstractModel): }, }) return res + + +class ResUsers(models.Model): + _inherit = "res.users" + + # Field name starts with 'context_' to allow modification by the user + # in his preferences, cf server/openerp/addons/base/res/res_users.py + # in "def write()" of "class res_users(osv.osv)" + context_propose_creation_crm_call = fields.Boolean( + string='Propose to create a call in CRM after a click2dial', + default=True) diff --git a/asterisk_click2dial_crm/res_users_view.xml b/crm_phone/res_users_view.xml similarity index 80% rename from asterisk_click2dial_crm/res_users_view.xml rename to crm_phone/res_users_view.xml index fa9641c..75589dc 100644 --- a/asterisk_click2dial_crm/res_users_view.xml +++ b/crm_phone/res_users_view.xml @@ -1,6 +1,6 @@ @@ -14,7 +14,7 @@ res.users - + @@ -26,12 +26,10 @@ res.users + - - 0 - diff --git a/crm_phone/wizard/__init__.py b/crm_phone/wizard/__init__.py index 1694fd8..967c5c8 100644 --- a/crm_phone/wizard/__init__.py +++ b/crm_phone/wizard/__init__.py @@ -20,3 +20,4 @@ ############################################################################## from . import number_not_found +from . import create_crm_phonecall diff --git a/crm_phone/wizard/create_crm_phonecall.py b/crm_phone/wizard/create_crm_phonecall.py new file mode 100644 index 0000000..f863b2e --- /dev/null +++ b/crm_phone/wizard/create_crm_phonecall.py @@ -0,0 +1,73 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# CRM Phone module for Odoo +# Copyright (c) 2012-2015 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, _ +import phonenumbers + + +class wizard_create_crm_phonecall(models.TransientModel): + _name = "wizard.create.crm.phonecall" + + @api.multi + def button_create_outgoing_phonecall(self): + self.ensure_one() + return self._create_open_crm_phonecall(crm_categ='Outbound') + + @api.model + def _create_open_crm_phonecall(self, crm_categ): + categ = self.with_context(lang='en_US').env['crm.case.categ'].search( + [('name', '=', crm_categ)]) + case_section = self.env['crm.case.section'].search( + [('member_ids', 'in', self._uid)]) + action_ctx = self.env.context.copy() + action_ctx.update({ + 'default_categ_id': categ and categ[0].id or False, + 'default_section_id': + case_section and case_section[0].id or False, + }) + domain = False + if self.env.context.get('click2dial_model') == 'res.partner': + partner_id = self.env.context.get('click2dial_id') + action_ctx['default_partner_id'] = partner_id + domain = [('partner_id', '=', partner_id)] + elif self.env.context.get('click2dial_model') == 'crm.lead': + lead_id = self.env.context.get('click2dial_id') + action_ctx['default_opportunity_id'] = lead_id + domain = [('opportunity_id', '=', lead_id)] + parsed_num = phonenumbers.parse(self.env.context.get('phone_number')) + number_type = phonenumbers.number_type(parsed_num) + if number_type == 1: + action_ctx['default_partner_mobile'] =\ + self.env.context.get('phone_number') + else: + action_ctx['default_partner_phone'] =\ + self.env.context.get('phone_number') + return { + 'name': _('Phone Call'), + 'domain': domain, + 'res_model': 'crm.phonecall', + 'view_mode': 'form,tree', + 'type': 'ir.actions.act_window', + 'nodestroy': False, # close the pop-up wizard after action + 'target': 'current', + 'context': action_ctx, + } diff --git a/asterisk_click2dial_crm/wizard/create_crm_phonecall_view.xml b/crm_phone/wizard/create_crm_phonecall_view.xml similarity index 100% rename from asterisk_click2dial_crm/wizard/create_crm_phonecall_view.xml rename to crm_phone/wizard/create_crm_phonecall_view.xml From f425949929dd9f80af306c7df097028cd701e922 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 12 Mar 2015 12:45:25 +0100 Subject: [PATCH 2/8] Add missing file --- asterisk_click2dial_crm/res_users_view.xml | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 asterisk_click2dial_crm/res_users_view.xml diff --git a/asterisk_click2dial_crm/res_users_view.xml b/asterisk_click2dial_crm/res_users_view.xml new file mode 100644 index 0000000..0c57f29 --- /dev/null +++ b/asterisk_click2dial_crm/res_users_view.xml @@ -0,0 +1,23 @@ + + + + + + + + asterisk.crm.preferences.option.view + res.users + + + + 0 + + + + + + From 27f024c160ddc4065f97b90fdce370ec1b89b313 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 12 Mar 2015 14:25:20 +0100 Subject: [PATCH 3/8] Remove an import that is not needed any more --- asterisk_click2dial/__openerp__.py | 2 +- asterisk_click2dial/asterisk_click2dial.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/asterisk_click2dial/__openerp__.py b/asterisk_click2dial/__openerp__.py index 060b879..108388c 100644 --- a/asterisk_click2dial/__openerp__.py +++ b/asterisk_click2dial/__openerp__.py @@ -96,7 +96,7 @@ http://www.akretion.com/products-and-services/openerp-asterisk-voip-connector 'author': "Akretion,Odoo Community Association (OCA)", 'website': 'http://www.akretion.com/', 'depends': ['base_phone'], - 'external_dependencies': {'python': ['phonenumbers', 'Asterisk']}, + 'external_dependencies': {'python': ['Asterisk']}, 'data': [ 'asterisk_server_view.xml', 'res_users_view.xml', diff --git a/asterisk_click2dial/asterisk_click2dial.py b/asterisk_click2dial/asterisk_click2dial.py index 84f90ab..5e45fff 100644 --- a/asterisk_click2dial/asterisk_click2dial.py +++ b/asterisk_click2dial/asterisk_click2dial.py @@ -22,8 +22,6 @@ from openerp.osv import fields, orm from openerp.tools.translate import _ import logging -# Lib for phone number reformating -> pip install phonenumbers -import phonenumbers try: # Lib py-asterisk from http://code.google.com/p/py-asterisk/ From 586296537b5d7333dcd9c121f64f8b7a97a3cafd Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 19 Mar 2015 22:52:19 +0100 Subject: [PATCH 4/8] Fully remove raise from write/create, to avoid a crash on module install with XML data for res.company + it's related partner with phone numbers FIX install wizard --- base_phone/base_phone.py | 13 +++++----- .../wizard/reformat_all_phonenumbers.py | 26 +++++++++++-------- .../wizard/reformat_all_phonenumbers_view.xml | 19 +++++++++----- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/base_phone/base_phone.py b/base_phone/base_phone.py index 2131978..d0dcaa5 100644 --- a/base_phone/base_phone.py +++ b/base_phone/base_phone.py @@ -77,13 +77,14 @@ class PhoneCommon(models.AbstractModel): 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 Warning( - _("You should set a country on the company '%s'") + _logger.error( + _("You should set a country on the company '%s' " + "to allow the reformat of phone numbers") % user.company_id.name) + user_countrycode = '' + # with country code = '', phonenumbers.parse() will work + # with phonenumbers formatted in E164, but will fail with + # phone numbers in national format for field in phonefields: if vals.get(field): init_value = vals.get(field) diff --git a/base_phone/wizard/reformat_all_phonenumbers.py b/base_phone/wizard/reformat_all_phonenumbers.py index f0eace7..a84eb2c 100644 --- a/base_phone/wizard/reformat_all_phonenumbers.py +++ b/base_phone/wizard/reformat_all_phonenumbers.py @@ -1,8 +1,8 @@ # -*- encoding: utf-8 -*- ############################################################################## # -# Base Phone module for OpenERP -# Copyright (C) 2012-2014 Alexis de Lattre +# Base Phone module for Odoo +# Copyright (C) 2012-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 @@ -19,20 +19,23 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp import models, fields import logging logger = logging.getLogger(__name__) -class reformat_all_phonenumbers(orm.TransientModel): +class reformat_all_phonenumbers(models.TransientModel): _name = "reformat.all.phonenumbers" + _inherit = "res.config.installer" _description = "Reformat all phone numbers" - _columns = { - 'phonenumbers_not_reformatted': fields.text( - "Phone numbers that couldn't be reformatted"), - } + phonenumbers_not_reformatted = fields.Text( + string="Phone numbers that couldn't be reformatted") + state = fields.Selection([ + ('draft', 'Draft'), + ('done', 'Done'), + ], string='State', default='draft') def run_reformat_all_phonenumbers(self, cr, uid, ids, context=None): logger.info('Starting to reformat all the phone numbers') @@ -95,9 +98,10 @@ class reformat_all_phonenumbers(orm.TransientModel): phonenumbers_not_reformatted = \ 'All phone numbers have been reformatted successfully.' self.write( - cr, uid, ids[0], - {'phonenumbers_not_reformatted': phonenumbers_not_reformatted}, - context=context) + cr, uid, ids[0], { + 'phonenumbers_not_reformatted': phonenumbers_not_reformatted, + 'state': 'done', + }, context=context) logger.info('End of the phone number reformatting wizard') action = self.pool['ir.actions.act_window'].for_xml_id( cr, uid, 'base_phone', 'reformat_all_phonenumbers_action', diff --git a/base_phone/wizard/reformat_all_phonenumbers_view.xml b/base_phone/wizard/reformat_all_phonenumbers_view.xml index 482f0a5..181620d 100644 --- a/base_phone/wizard/reformat_all_phonenumbers_view.xml +++ b/base_phone/wizard/reformat_all_phonenumbers_view.xml @@ -12,16 +12,21 @@ reformat_all_phonenumbers.form reformat.all.phonenumbers -
- + -
-
From 62cb85c470c11bdad9d0ab3da0e51d582ca4d34c Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 20 Mar 2015 01:00:38 +0100 Subject: [PATCH 5/8] If you enter a phone number in national format, it is now interpreted from the country of the object (partner, lead, hr.applicant), not from the country of the user... a very wanted feature ! --- base_phone/base_phone.py | 107 ++++++++++--------- crm_claim_phone/crm_claim_phone.py | 7 +- crm_phone/crm_phone.py | 16 ++- event_phone/event_phone.py | 8 +- hr_phone/hr_phone.py | 8 +- hr_recruitment_phone/hr_recruitment_phone.py | 8 +- 6 files changed, 91 insertions(+), 63 deletions(-) diff --git a/base_phone/base_phone.py b/base_phone/base_phone.py index d0dcaa5..07a86a4 100644 --- a/base_phone/base_phone.py +++ b/base_phone/base_phone.py @@ -20,6 +20,7 @@ ############################################################################## from openerp import models, fields, api, _ +from openerp.tools.safe_eval import safe_eval from openerp.exceptions import Warning import logging # Lib for phone number reformating -> pip install phonenumbers @@ -31,66 +32,65 @@ _logger = logging.getLogger(__name__) class PhoneCommon(models.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=None, - context=None): + def _generic_reformat_phonenumbers( + self, cr, uid, ids, vals, context=None): """Reformat phone numbers in E.164 format i.e. +33141981242""" + assert isinstance(self._country_field, (str, unicode, type(None))),\ + 'Wrong self._country_field' + assert isinstance(self._partner_field, (str, unicode, type(None))),\ + 'Wrong self._partner_field' + assert isinstance(self._phone_fields, list),\ + 'self._phone_fields must be a list' if context is None: context = {} - if phonefields is None: - phonefields = [ - 'phone', 'partner_phone', 'work_phone', 'fax', - 'mobile', 'partner_mobile', 'mobile_phone', - ] - if any([vals.get(field) for field in phonefields]): + if ids and isinstance(ids, (int, long)): + ids = [ids] + if any([vals.get(field) for field in self._phone_fields]): 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: - _logger.error( - _("You should set a country on the company '%s' " - "to allow the reformat of phone numbers") - % user.company_id.name) - user_countrycode = '' - # with country code = '', phonenumbers.parse() will work + countrycode = None + if self._country_field: + if vals.get(self._country_field): + country = self.pool['res.country'].browse( + cr, uid, vals[self._country_field], context=context) + countrycode = country.code + elif ids: + rec = self.browse(cr, uid, ids[0], context=context) + country = safe_eval( + 'rec.' + self._country_field, {'rec': rec}) + countrycode = country and country.code or None + elif self._partner_field: + if vals.get(self._partner_field): + partner = self.pool['res.partner'].browse( + cr, uid, vals[self._partner_field], context=context) + countrycode = partner.country_id and\ + partner.country_id.code or None + elif ids: + rec = self.browse(cr, uid, ids[0], context=context) + partner = safe_eval( + 'rec.' + self._partner_field, {'rec': rec}) + if partner: + countrycode = partner.country_id and\ + partner.country_id.code or None + if not countrycode: + if user.company_id.country_id: + countrycode = user.company_id.country_id.code + else: + _logger.error( + _("You should set a country on the company '%s' " + "to allow the reformat of phone numbers") + % user.company_id.name) + countrycode = None + # with country code = None, phonenumbers.parse() will work # with phonenumbers formatted in E164, but will fail with # phone numbers in national format - for field in phonefields: + for field in self._phone_fields: if vals.get(field): init_value = vals.get(field) try: res_parse = phonenumbers.parse( - vals.get(field), user_countrycode) + vals.get(field), countrycode) vals[field] = phonenumbers.format_number( res_parse, phonenumbers.PhoneNumberFormat.E164) if init_value != vals[field]: @@ -105,7 +105,8 @@ class PhoneCommon(models.AbstractModel): # via the webservices _logger.error( "Cannot reformat the phone number '%s' to " - "international format" % vals.get(field)) + "international format with region=%s" + % (vals.get(field), countrycode)) if context.get('raise_if_phone_parse_fails'): raise Warning( _("Cannot reformat the phone number '%s' to " @@ -241,16 +242,20 @@ class PhoneCommon(models.AbstractModel): class ResPartner(models.Model): _name = 'res.partner' _inherit = ['res.partner', 'phone.common'] + _phone_fields = ['phone', 'mobile', 'fax'] + _phone_name_sequence = 10 + _country_field = 'country_id' + _partner_field = None def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, vals, context=context) return super(ResPartner, 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) + cr, uid, ids, vals, context=context) return super(ResPartner, self).write( cr, uid, ids, vals_reformated, context=context) diff --git a/crm_claim_phone/crm_claim_phone.py b/crm_claim_phone/crm_claim_phone.py index a9996ef..9465bef 100644 --- a/crm_claim_phone/crm_claim_phone.py +++ b/crm_claim_phone/crm_claim_phone.py @@ -26,16 +26,19 @@ from openerp.osv import orm class crm_claim(orm.Model): _name = 'crm.claim' _inherit = ['crm.claim', 'phone.common'] + _phone_fields = ['partner_phone'] + _country_field = None + _partner_field = 'partner_id' def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, 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) + cr, uid, ids, vals, context=context) return super(crm_claim, self).write( cr, uid, ids, vals_reformated, context=context) diff --git a/crm_phone/crm_phone.py b/crm_phone/crm_phone.py index 42e61b0..9264e67 100644 --- a/crm_phone/crm_phone.py +++ b/crm_phone/crm_phone.py @@ -26,16 +26,20 @@ from openerp import models, fields class CrmLead(models.Model): _name = 'crm.lead' _inherit = ['crm.lead', 'phone.common'] + _phone_fields = ['phone', 'mobile', 'fax'] + _phone_name_sequence = 20 + _country_field = 'country_id' + _partner_field = None def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, vals, context=context) return super(CrmLead, 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) + cr, uid, ids, vals, context=context) return super(CrmLead, self).write( cr, uid, ids, vals_reformated, context=context) @@ -65,16 +69,20 @@ class CrmLead(models.Model): class CrmPhonecall(models.Model): _name = 'crm.phonecall' _inherit = ['crm.phonecall', 'phone.common'] + _phone_fields = ['partner_phone', 'partner_mobile'] + _country_field = None + _partner_field = 'partner_id' + def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, vals, context=context) return super(CrmPhonecall, 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) + cr, uid, ids, vals, context=context) return super(CrmPhonecall, self).write( cr, uid, ids, vals_reformated, context=context) diff --git a/event_phone/event_phone.py b/event_phone/event_phone.py index e06f9ff..b35a538 100644 --- a/event_phone/event_phone.py +++ b/event_phone/event_phone.py @@ -26,16 +26,20 @@ from openerp.osv import orm class event_registration(orm.Model): _name = 'event.registration' _inherit = ['event.registration', 'phone.common'] + _phone_fields = ['phone'] + _phone_name_sequence = 100 + _country_field = None + _partner_field = 'partner_id' def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, 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) + cr, uid, ids, vals, context=context) return super(event_registration, self).write( cr, uid, ids, vals_reformated, context=context) diff --git a/hr_phone/hr_phone.py b/hr_phone/hr_phone.py index 444c16d..0126e4f 100644 --- a/hr_phone/hr_phone.py +++ b/hr_phone/hr_phone.py @@ -26,16 +26,20 @@ from openerp.osv import orm class hr_employee(orm.Model): _name = 'hr.employee' _inherit = ['hr.employee', 'phone.common'] + _phone_fields = ['work_phone', 'mobile_phone'] + _phone_name_sequence = 30 + _country_field = 'country_id' + _partner_field = None def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, vals, context=context) return super(hr_employee, 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) + cr, uid, ids, vals, context=context) return super(hr_employee, self).write( cr, uid, ids, vals_reformated, context=context) diff --git a/hr_recruitment_phone/hr_recruitment_phone.py b/hr_recruitment_phone/hr_recruitment_phone.py index 8652e23..fc93ee5 100644 --- a/hr_recruitment_phone/hr_recruitment_phone.py +++ b/hr_recruitment_phone/hr_recruitment_phone.py @@ -26,16 +26,20 @@ from openerp.osv import orm class hr_applicant(orm.Model): _name = 'hr.applicant' _inherit = ['hr.applicant', 'phone.common'] + _phone_fields = ['partner_phone', 'partner_mobile'] + _phone_name_sequence = 50 + _country_field = None + _partner_field = 'partner_id' def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( - cr, uid, vals, context=context) + cr, uid, None, vals, context=context) return super(hr_applicant, 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) + cr, uid, ids, vals, context=context) return super(hr_applicant, self).write( cr, uid, ids, vals_reformated, context=context) From ae40e741ef8125daead50c2ba162aafc4560eee5 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 20 Mar 2015 09:06:18 +0000 Subject: [PATCH 6/8] Continue to adapt the code to the recent changes --- base_phone/wizard/reformat_all_phonenumbers.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/base_phone/wizard/reformat_all_phonenumbers.py b/base_phone/wizard/reformat_all_phonenumbers.py index a84eb2c..00310c8 100644 --- a/base_phone/wizard/reformat_all_phonenumbers.py +++ b/base_phone/wizard/reformat_all_phonenumbers.py @@ -70,18 +70,17 @@ class reformat_all_phonenumbers(models.TransientModel): # _generic_reformat_phonenumbers() try: obj._generic_reformat_phonenumbers( - cr, uid, entry, context=ctx_raise) + cr, uid, [entry['id']], entry, context=ctx_raise) except Exception, e: name = obj.name_get( cr, uid, [init_entry['id']], context=context)[0][1] + err_msg = e and len(e) > 1 and e[1] or 'missing error msg' phonenumbers_not_reformatted += \ "Problem on %s '%s'. Error message: %s\n" % ( - obj._description, - name, e[1]) + obj._description, name, err_msg) logger.warning( "Problem on %s '%s'. Error message: %s" % ( - obj._description, - name, e[1])) + obj._description, name, err_msg)) continue if any( [init_entry.get(field) From b4522e78c8dc96007755c422442699a7f6155804 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Fri, 20 Mar 2015 22:00:33 +0100 Subject: [PATCH 7/8] More Yaml tests Use the new phone attributes on objects inside the code --- base_phone/base_phone.py | 84 +++++++++---------- base_phone/test/phonenum.yml | 8 ++ .../wizard/reformat_all_phonenumbers.py | 10 +-- crm_claim_phone/crm_claim_phone.py | 12 --- crm_phone/__openerp__.py | 1 + crm_phone/crm_phone.py | 19 ----- crm_phone/test/phonenum.yml | 41 +++++++++ event_phone/event_phone.py | 13 --- hr_phone/hr_phone.py | 13 --- hr_recruitment_phone/hr_recruitment_phone.py | 13 --- 10 files changed, 95 insertions(+), 119 deletions(-) create mode 100644 crm_phone/test/phonenum.yml diff --git a/base_phone/base_phone.py b/base_phone/base_phone.py index 07a86a4..778c02a 100644 --- a/base_phone/base_phone.py +++ b/base_phone/base_phone.py @@ -114,26 +114,21 @@ class PhoneCommon(models.AbstractModel): % (vals.get(field), e)) return vals - def get_name_from_phone_number( - self, cr, uid, presented_number, context=None): + @api.model + def get_name_from_phone_number(self, presented_number): '''Function to get name from phone number. Usefull for use from IPBX to add CallerID name to incoming calls.''' - res = self.get_record_from_phone_number( - cr, uid, presented_number, context=context) + res = self.get_record_from_phone_number(presented_number) if res: return res[2] else: return False - def get_record_from_phone_number( - self, cr, uid, presented_number, context=None): + @api.model + def get_record_from_phone_number(self, presented_number): '''If it finds something, it returns (object name, ID, record name) For example : ('res.partner', 42, u'Alexis de Lattre (Akretion)') ''' - if context is None: - context = {} - ctx_phone = context.copy() - ctx_phone['callerid'] = True _logger.debug( u"Call get_name_from_phone_number with number = %s" % presented_number) @@ -146,48 +141,47 @@ class PhoneCommon(models.AbstractModel): _logger.warning( u"Number '%s' should only contain digits." % presented_number) - user = self.pool['res.users'].browse(cr, uid, uid, context=context) nr_digits_to_match_from_end = \ - user.company_id.number_of_digits_to_match_from_end + self.env.user.company_id.number_of_digits_to_match_from_end if len(presented_number) >= nr_digits_to_match_from_end: end_number_to_match = presented_number[ -nr_digits_to_match_from_end:len(presented_number)] else: end_number_to_match = presented_number - phonefieldsdict = self._get_phone_fields(cr, uid, context=context) - phonefieldslist = [] - for objname, prop in phonefieldsdict.iteritems(): - if prop.get('get_name_sequence'): - phonefieldslist.append({objname: prop}) + phoneobjects = self._get_phone_fields() + phonefieldslist = [] # [('res.parter', 10), ('crm.lead', 20)] + for objname in phoneobjects: + if ( + '_phone_name_sequence' in dir(self.env[objname]) and + self.env[objname]._phone_name_sequence): + phonefieldslist.append( + (objname, self.env[objname]._phone_name_sequence)) phonefieldslist_sorted = sorted( phonefieldslist, - key=lambda element: element.values()[0]['get_name_sequence']) - - for phonedict in phonefieldslist_sorted: - objname = phonedict.keys()[0] - prop = phonedict.values()[0] - phonefields = prop['phonefields'] - obj = self.pool[objname] + key=lambda element: element[1]) + _logger.debug('phonefieldslist_sorted=%s' % phonefieldslist_sorted) + for (objname, prio) in phonefieldslist_sorted: + obj = self.with_context(callerid=True).env[objname] pg_search_number = str('%' + end_number_to_match) _logger.debug( "Will search phone and mobile numbers in %s ending with '%s'" % (objname, end_number_to_match)) domain = [] - for phonefield in phonefields: + for phonefield in obj._phone_fields: domain.append((phonefield, '=like', pg_search_number)) - if len(phonefields) > 1: - domain = ['|'] * (len(phonefields) - 1) + domain - res_ids = obj.search(cr, uid, domain, context=context) - if len(res_ids) > 1: + if len(obj._phone_fields) > 1: + domain = ['|'] * (len(obj._phone_fields) - 1) + domain + res_obj = obj.search(domain) + if len(res_obj) > 1: _logger.warning( u"There are several %s (IDS = %s) with a phone number " "ending with '%s'. Taking the first one." - % (objname, res_ids, end_number_to_match)) - if res_ids: - name = obj.name_get( - cr, uid, res_ids[0], context=ctx_phone)[0][1] - res = (objname, res_ids[0], name) + % (objname, res_obj.ids, end_number_to_match)) + res_obj = res_obj[0] + if res_obj: + name = res_obj.name_get()[0][1] + res = (objname, res_obj.id, name) _logger.debug( u"Answer get_record_from_phone_number: (%s, %d, %s)" % (res[0], res[1], res[2])) @@ -198,16 +192,22 @@ class PhoneCommon(models.AbstractModel): % (objname, end_number_to_match)) return False - def _get_phone_fields(self, cr, uid, context=None): + @api.model + def _get_phone_fields(self): '''Returns a dict with key = object name and value = list of phone fields''' - res = { - 'res.partner': { - 'phonefields': ['phone', 'mobile'], - 'faxfields': ['fax'], - 'get_name_sequence': 10, - }, - } + models = self.env['ir.model'].search([('osv_memory', '=', False)]) + res = [] + for model in models: + senv = False + try: + senv = self.env[model.model] + except: + continue + if ( + '_phone_fields' in dir(senv) and + isinstance(senv._phone_fields, list)): + res.append(model.model) return res def click2dial(self, cr, uid, erp_number, context=None): diff --git a/base_phone/test/phonenum.yml b/base_phone/test/phonenum.yml index 5b92efb..e1e320e 100644 --- a/base_phone/test/phonenum.yml +++ b/base_phone/test/phonenum.yml @@ -35,3 +35,11 @@ !python {model: res.partner}: | partner3 = self.browse(cr, uid, ref('partner3'), context=context) assert partner3.phone == '42', 'Invalid phone numbers should not be changed' +- + Get name from phone number +- + !python {model: phone.common}: | + name = self.get_name_from_phone_number(cr, uid, '0642774266') + assert name == 'Pierre Paillet', 'Wrong result for get_name_from_phone_number' + name2 = self.get_name_from_phone_number(cr, uid, '0041216191010') + assert name2 == u'Joël Grand-Guillaume (Camptocamp)', 'Wrong result for get_name_from_phone_number (partner2)' diff --git a/base_phone/wizard/reformat_all_phonenumbers.py b/base_phone/wizard/reformat_all_phonenumbers.py index 00310c8..ad64372 100644 --- a/base_phone/wizard/reformat_all_phonenumbers.py +++ b/base_phone/wizard/reformat_all_phonenumbers.py @@ -40,16 +40,12 @@ class reformat_all_phonenumbers(models.TransientModel): 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.pool['phone.common']._get_phone_fields( + phoneobjects = self.pool['phone.common']._get_phone_fields( cr, uid, context=context) ctx_raise = dict(context, raise_if_phone_parse_fails=True) - for objname, prop in toreformat_dict.iteritems(): - fields = [] + for objname in phoneobjects: + fields = self.pool[objname]._phone_fields obj = self.pool[objname] - if prop.get('phonefields'): - fields += prop['phonefields'] - if prop.get('faxfields'): - fields += prop['faxfields'] logger.info( 'Starting to reformat phone numbers on object %s ' '(fields = %s)' % (objname, fields)) diff --git a/crm_claim_phone/crm_claim_phone.py b/crm_claim_phone/crm_claim_phone.py index 9465bef..5093964 100644 --- a/crm_claim_phone/crm_claim_phone.py +++ b/crm_claim_phone/crm_claim_phone.py @@ -41,15 +41,3 @@ class crm_claim(orm.Model): cr, uid, ids, vals, context=context) return super(crm_claim, self).write( cr, uid, ids, vals_reformated, context=context) - - -class phone_common(orm.AbstractModel): - _inherit = 'phone.common' - - def _get_phone_fields(self, cr, uid, context=None): - res = super(phone_common, self)._get_phone_fields( - cr, uid, context=context) - res['crm.claim'] = { - 'phonefields': ['partner_phone'], - } - return res diff --git a/crm_phone/__openerp__.py b/crm_phone/__openerp__.py index f2978bf..8dc11c3 100644 --- a/crm_phone/__openerp__.py +++ b/crm_phone/__openerp__.py @@ -49,6 +49,7 @@ for any help or question about this module. 'wizard/number_not_found_view.xml', 'wizard/create_crm_phonecall_view.xml', ], + 'test': ['test/phonenum.yml'], 'images': [], 'installable': True, 'auto_install': True, diff --git a/crm_phone/crm_phone.py b/crm_phone/crm_phone.py index 9264e67..07a1d85 100644 --- a/crm_phone/crm_phone.py +++ b/crm_phone/crm_phone.py @@ -87,25 +87,6 @@ class CrmPhonecall(models.Model): cr, uid, ids, vals_reformated, context=context) -class PhoneCommon(models.AbstractModel): - _inherit = 'phone.common' - - def _get_phone_fields(self, cr, uid, context=None): - res = super(PhoneCommon, self)._get_phone_fields( - cr, uid, context=context) - res.update({ - 'crm.lead': { - 'phonefields': ['phone', 'mobile'], - 'faxfields': ['fax'], - 'get_name_sequence': 20, - }, - 'crm.phonecall': { - 'phonefields': ['partner_phone', 'partner_mobile'], - }, - }) - return res - - class ResUsers(models.Model): _inherit = "res.users" diff --git a/crm_phone/test/phonenum.yml b/crm_phone/test/phonenum.yml new file mode 100644 index 0000000..25aa860 --- /dev/null +++ b/crm_phone/test/phonenum.yml @@ -0,0 +1,41 @@ +- + Write french phone numbers in national format +- + !record {model: crm.lead, id: lead1}: + name: Jacques Toufaux + mobile: 06 42 77 42 77 + fax: (0) 1 45 44 42 43 + country_id: base.fr +- + Write swiss phone numbers in national format +- + !record {model: crm.lead, id: lead2}: + name: Michel Content + country_id: base.ch + phone: 04 31 23 45 67 +- + Create a german lead +- + !record {model: crm.lead, id: lead3}: + name: Angela Strasse + country_id: base.de +- + Check that valid phone numbers have been converted to E.164 +- + !python {model: crm.lead}: | + lead1 = self.browse(cr, uid, ref('lead1'), context=context) + assert lead1.mobile == '+33642774277', 'Mobile number not written in E.164 format (lead1)' + assert lead1.fax == '+33145444243', 'Fax number not written in E.164 format (lead1)' + lead2 = self.browse(cr, uid, ref('lead2'), context=context) + assert lead2.phone == '+41431234567', 'Phone number not written in E.164 format (lead2)' + self.write(cr, uid, ref('lead3'), {'phone': '0891234567'}) + lead3 = self.browse(cr, uid, ref('lead3'), context=context) + assert lead3.phone == '+49891234567', 'Phone number not written in E.164 format (lead3)' +- + Get name from phone number +- + !python {model: phone.common}: | + name = self.get_name_from_phone_number(cr, uid, '0642774277') + assert name == 'Jacques Toufaux', 'Wrong result for get_name_from_phone_number (lead1)' + name2 = self.get_name_from_phone_number(cr, uid, '0041431234567') + assert name2 == 'Michel Content', 'Wrong result for get_name_from_phone_number (lead2)' diff --git a/event_phone/event_phone.py b/event_phone/event_phone.py index b35a538..7f7e3bb 100644 --- a/event_phone/event_phone.py +++ b/event_phone/event_phone.py @@ -42,16 +42,3 @@ class event_registration(orm.Model): cr, uid, ids, vals, context=context) return super(event_registration, self).write( cr, uid, ids, vals_reformated, context=context) - - -class phone_common(orm.AbstractModel): - _inherit = 'phone.common' - - def _get_phone_fields(self, cr, uid, context=None): - res = super(phone_common, self)._get_phone_fields( - cr, uid, context=context) - res['event.registration'] = { - 'phonefields': ['phone'], - 'get_name_sequence': 100, - } - return res diff --git a/hr_phone/hr_phone.py b/hr_phone/hr_phone.py index 0126e4f..3844a85 100644 --- a/hr_phone/hr_phone.py +++ b/hr_phone/hr_phone.py @@ -42,16 +42,3 @@ class hr_employee(orm.Model): cr, uid, ids, vals, context=context) return super(hr_employee, self).write( cr, uid, ids, vals_reformated, context=context) - - -class phone_common(orm.AbstractModel): - _inherit = 'phone.common' - - def _get_phone_fields(self, cr, uid, context=None): - res = super(phone_common, self)._get_phone_fields( - cr, uid, context=context) - res['hr.employee'] = { - 'phonefields': ['work_phone', 'mobile_phone'], - 'get_name_sequence': 30, - } - return res diff --git a/hr_recruitment_phone/hr_recruitment_phone.py b/hr_recruitment_phone/hr_recruitment_phone.py index fc93ee5..cdbdfa9 100644 --- a/hr_recruitment_phone/hr_recruitment_phone.py +++ b/hr_recruitment_phone/hr_recruitment_phone.py @@ -42,16 +42,3 @@ class hr_applicant(orm.Model): cr, uid, ids, vals, context=context) return super(hr_applicant, self).write( cr, uid, ids, vals_reformated, context=context) - - -class phone_common(orm.AbstractModel): - _inherit = 'phone.common' - - def _get_phone_fields(self, cr, uid, context=None): - res = super(phone_common, self)._get_phone_fields( - cr, uid, context=context) - res['hr.applicant'] = { - 'phonefields': ['partner_phone', 'partner_mobile'], - 'get_name_sequence': 50, - } - return res From 007504e4d214ba29591e75feb198cb5a4d1862ee Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Sat, 21 Mar 2015 00:53:24 +0100 Subject: [PATCH 8/8] Flake8 fix --- crm_phone/crm_phone.py | 1 - 1 file changed, 1 deletion(-) diff --git a/crm_phone/crm_phone.py b/crm_phone/crm_phone.py index 07a1d85..3558fb7 100644 --- a/crm_phone/crm_phone.py +++ b/crm_phone/crm_phone.py @@ -73,7 +73,6 @@ class CrmPhonecall(models.Model): _country_field = None _partner_field = 'partner_id' - def create(self, cr, uid, vals, context=None): vals_reformated = self._generic_reformat_phonenumbers( cr, uid, None, vals, context=context)