Browse Source
Extract Asterisk-independant code (the widget="phone" + phone number reformatting) from the asterisk_click2dial module to a new base_phone module.
pull/7/head
Extract Asterisk-independant code (the widget="phone" + phone number reformatting) from the asterisk_click2dial module to a new base_phone module.
pull/7/head
Alexis de Lattre
11 years ago
27 changed files with 516 additions and 268 deletions
-
11asterisk_click2dial/__openerp__.py
-
66asterisk_click2dial/asterisk_click2dial.py
-
15asterisk_click2dial/asterisk_server_view.xml
-
4asterisk_click2dial/res_partner_view.xml
-
3asterisk_click2dial/wizard/__init__.py
-
73asterisk_click2dial/wizard/reformat_all_phonenumbers.py
-
32asterisk_click2dial_crm/__openerp__.py
-
31asterisk_click2dial_crm/asterisk_click2dial_crm.py
-
6asterisk_click2dial_crm/wizard/__init__.py
-
33asterisk_click2dial_crm/wizard/create_crm_phonecall.py
-
13asterisk_click2dial_crm/wizard/reformat_all_phonenumbers.py
-
43asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py
-
8asterisk_click2dial_crm_claim/wizard/open_calling_partner.py
-
13asterisk_click2dial_crm_claim/wizard/reformat_all_phonenumbers.py
-
8asterisk_click2dial_registration/__openerp__.py
-
23asterisk_click2dial_registration/asterisk_click2dial_registration.py
-
4asterisk_click2dial_registration/wizard/open_calling_partner.py
-
23base_phone/__init__.py
-
55base_phone/__openerp__.py
-
120base_phone/base_phone.py
-
50base_phone/res_partner_view.xml
-
0base_phone/static/lib/js/PhoneFormat.js
-
16base_phone/static/src/js/phone_widget.js
-
0base_phone/static/src/xml/phone.xml
-
22base_phone/wizard/__init__.py
-
100base_phone/wizard/reformat_all_phonenumbers.py
-
10base_phone/wizard/reformat_all_phonenumbers_view.xml
@ -1,73 +0,0 @@ |
|||||
# -*- encoding: utf-8 -*- |
|
||||
############################################################################## |
|
||||
# |
|
||||
# Asterisk Click2dial module for OpenERP |
|
||||
# Copyright (C) 2012-2013 Alexis de Lattre <alexis@via.ecp.fr> |
|
||||
# |
|
||||
# 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 <http://www.gnu.org/licenses/>. |
|
||||
# |
|
||||
############################################################################## |
|
||||
|
|
||||
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 |
|
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Base Module module for OpenERP |
||||
|
# Copyright (C) 2014 Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
# |
||||
|
# 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from . import base_phone |
||||
|
from . import wizard |
@ -0,0 +1,55 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Base Phone module for OpenERP |
||||
|
# Copyright (C) 2014 Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
# |
||||
|
# 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
|
||||
|
{ |
||||
|
'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 <alexis.delattre@akretion.com> 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, |
||||
|
} |
@ -0,0 +1,120 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Base Phone module for OpenERP |
||||
|
# Copyright (C) 2010-2014 Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
# |
||||
|
# 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
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) |
@ -0,0 +1,50 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<!-- |
||||
|
Base Phone module for OpenERP |
||||
|
Copyright (C) 2010-2014 Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
The licence is in the file __openerp__.py |
||||
|
--> |
||||
|
|
||||
|
<openerp> |
||||
|
<data> |
||||
|
|
||||
|
<record id="view_partner_simple_form" model="ir.ui.view"> |
||||
|
<field name="name">base.phone.res.partner.simplified.form</field> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="inherit_id" ref="base.view_partner_simple_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="phone" position="attributes"> |
||||
|
<attribute name="widget">phone</attribute> |
||||
|
</field> |
||||
|
<field name="mobile" position="attributes"> |
||||
|
<attribute name="widget">phone</attribute> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="view_partner_form" model="ir.ui.view"> |
||||
|
<field name="name">base.phone.res.partner.form</field> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="inherit_id" ref="base.view_partner_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//group/group/field[@name='phone']" position="attributes"> |
||||
|
<attribute name="widget">phone</attribute> |
||||
|
</xpath> |
||||
|
<xpath expr="//group/group/field[@name='mobile']" position="attributes"> |
||||
|
<attribute name="widget">phone</attribute> |
||||
|
</xpath> |
||||
|
<xpath expr="//group/group/field[@name='fax']" position="attributes"> |
||||
|
<attribute name="widget">fax</attribute> |
||||
|
</xpath> |
||||
|
<xpath expr="//form[@string='Contact']/sheet/group/field[@name='phone']" position="attributes"> |
||||
|
<attribute name="widget">phone</attribute> |
||||
|
</xpath> |
||||
|
<xpath expr="//form[@string='Contact']/sheet/group/field[@name='mobile']" position="attributes"> |
||||
|
<attribute name="widget">phone</attribute> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
|
||||
|
</data> |
||||
|
</openerp> |
@ -0,0 +1,22 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Base Phone module for OpenERP |
||||
|
# Copyright (C) 2012-2014 Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
# |
||||
|
# 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
from . import reformat_all_phonenumbers |
@ -0,0 +1,100 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
############################################################################## |
||||
|
# |
||||
|
# Base Phone module for OpenERP |
||||
|
# Copyright (C) 2012-2014 Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
# |
||||
|
# 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 <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################## |
||||
|
|
||||
|
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 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue