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
Alexis de Lattre 11 years ago
parent
commit
10acdf7bdc
  1. 11
      asterisk_click2dial/__openerp__.py
  2. 66
      asterisk_click2dial/asterisk_click2dial.py
  3. 15
      asterisk_click2dial/asterisk_server_view.xml
  4. 4
      asterisk_click2dial/res_partner_view.xml
  5. 3
      asterisk_click2dial/wizard/__init__.py
  6. 73
      asterisk_click2dial/wizard/reformat_all_phonenumbers.py
  7. 20
      asterisk_click2dial_crm/__openerp__.py
  8. 31
      asterisk_click2dial_crm/asterisk_click2dial_crm.py
  9. 6
      asterisk_click2dial_crm/wizard/__init__.py
  10. 33
      asterisk_click2dial_crm/wizard/create_crm_phonecall.py
  11. 13
      asterisk_click2dial_crm/wizard/reformat_all_phonenumbers.py
  12. 43
      asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py
  13. 8
      asterisk_click2dial_crm_claim/wizard/open_calling_partner.py
  14. 13
      asterisk_click2dial_crm_claim/wizard/reformat_all_phonenumbers.py
  15. 6
      asterisk_click2dial_registration/__openerp__.py
  16. 23
      asterisk_click2dial_registration/asterisk_click2dial_registration.py
  17. 4
      asterisk_click2dial_registration/wizard/open_calling_partner.py
  18. 23
      base_phone/__init__.py
  19. 55
      base_phone/__openerp__.py
  20. 120
      base_phone/base_phone.py
  21. 50
      base_phone/res_partner_view.xml
  22. 0
      base_phone/static/lib/js/PhoneFormat.js
  23. 14
      base_phone/static/src/js/phone_widget.js
  24. 0
      base_phone/static/src/xml/phone.xml
  25. 22
      base_phone/wizard/__init__.py
  26. 100
      base_phone/wizard/reformat_all_phonenumbers.py
  27. 10
      base_phone/wizard/reformat_all_phonenumbers_view.xml

11
asterisk_click2dial/__openerp__.py

@ -2,7 +2,7 @@
##############################################################################
#
# Asterisk Click2dial module for OpenERP
# Copyright (C) 2010-2013 Alexis de Lattre <alexis@via.ecp.fr>
# 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
@ -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,
}

66
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

15
asterisk_click2dial/asterisk_server_view.xml

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Asterisk Click2dial module for OpenERP
Copyright (C) 2010-2013 Alexis de Lattre <alexis@via.ecp.fr>
Copyright (C) 2010-2014 Alexis de Lattre <alexis@via.ecp.fr>
The licence is in the file __openerp__.py
-->
@ -14,8 +14,8 @@
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form" />
<field name="arch" type="xml">
<notebook>
<page position="inside" string="IPBX">
<notebook position="inside">
<page name="asterisk" string="IPBX">
<field nolabel="1" name="asterisk_server_ids" />
</page>
</notebook>
@ -74,7 +74,7 @@
<field name="name">asterisk.server.tree</field>
<field name="model">asterisk.server</field>
<field name="arch" type="xml">
<tree string="Asterisk servers">
<tree string="Asterisk Servers">
<field name="company_id" invisible="not context.get('asterisk_server_main_view', False)"/>
<field name="name" />
<field name="ip_address" />
@ -86,16 +86,15 @@
<!-- Action for asterisk.server -->
<record id="action_asterisk_server" model="ir.actions.act_window">
<field name="name">Asterisk servers</field>
<field name="name">Asterisk Servers</field>
<field name="res_model">asterisk.server</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'asterisk_server_main_view': True}</field>
</record>
<!-- Menu entry under Settings > Technical -->
<menuitem id="menu_asterisk_servers" name="Asterisk" parent="base.menu_custom"/>
<menuitem action="action_asterisk_server" id="act_menu_ast_server" parent="menu_asterisk_servers" sequence="50"/>
<!-- Menu entry under Settings > Technical > Phone -->
<menuitem action="action_asterisk_server" id="act_menu_ast_server" parent="base_phone.menu_config_phone" sequence="50"/>
</data>

4
asterisk_click2dial/res_partner_view.xml

@ -15,7 +15,7 @@
<field name="name">asterisk.res.partner.simplified.form.dial</field>
<field name="model">res.partner</field>
<field name="priority">15</field>
<field name="inherit_id" ref="base.view_partner_simple_form"/>
<field name="inherit_id" ref="base_phone.view_partner_simple_form"/>
<field name="arch" type="xml">
<field name="phone" position="replace">
<group colspan="2" col="8">
@ -36,7 +36,7 @@
<field name="name">asterisk.res.partner.form.dial</field>
<field name="model">res.partner</field>
<field name="priority">15</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="inherit_id" ref="base_phone.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//group/group/field[@name='phone']" position="replace">
<group colspan="2" col="8">

3
asterisk_click2dial/wizard/__init__.py

@ -2,7 +2,7 @@
##############################################################################
#
# Asterisk Click2Dial module for OpenERP
# Copyright (C) 2012-2013 Alexis de Lattre <alexis@via.ecp.fr>
# 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
@ -19,5 +19,4 @@
#
##############################################################################
from . import reformat_all_phonenumbers
from . import open_calling_partner

73
asterisk_click2dial/wizard/reformat_all_phonenumbers.py

@ -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

20
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 <jmartin@zikzakmedia.com>
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
#
# 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,
@ -30,20 +30,16 @@
"license": "AGPL-3",
"category": "Customer Relationship Management",
"description": """
Asterisk Click2dial CRM
=======================
This module adds CRM-specific features to the asterisk_click2dial module.
It adds 2 features :
First, when you do a click2dial, OpenERP will propose you to create an
outbound phone call in the CRM ; if you answer 'Yes', it will create the phone
call in the CRM and open it in a new tab. If some users don't want to be asked
to create a phone call in the CRM each time they do a click2dial, you
should disable the corresponding option in the 'Telephony' tab of the 'User'
form.
First, when you do a click2dial, OpenERP will propose you to create an outbound phone call in the CRM ; if you answer 'Yes', it will create the phone call in the CRM and open it in a new tab. If some users don't want to be asked to create a phone call in the CRM each time they do a click2dial, you should disable the corresponding option in the 'Telephony' tab of the 'User' form.
Second, when you receive a phone call and run the wizard "Open calling partner",
if the partner is found in OpenERP, you will see a button that proposes to create
an inbound phone call in the CRM.
Second, when you receive a phone call and run the wizard "Open calling partner", if the partner is found in OpenERP, you will see a button that proposes to create an inbound phone call in the CRM.
This module has been initially developped by Zikzakmedia and has been enhanced by Akretion.

31
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 <contact@invitu.com>
# @author: Jesús Martín <jmartin@zikzakmedia.com>
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
#
# 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)

6
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 <alexis.delattre@akretion.com>
#
# 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,

33
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 <jmartin@zikzakmedia.com>
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
#
# 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 {
@ -59,13 +64,13 @@ class wizard_create_crm_phonecall(orm.TransientModel):
}
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

13
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 <alexis.delattre@akretion.com>
#
# 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',
}

43
asterisk_click2dial_crm_claim/asterisk_click2dial_crm_claim.py

@ -5,8 +5,8 @@
# Copyright (C) 2013 Invitu <contact@invitu.com>
#
# 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)

8
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 <alexis.delattre@akretion.com>
#
# 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)

13
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 <alexis.delattre@akretion.com>
#
# 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',
}

6
asterisk_click2dial_registration/__openerp__.py

@ -5,8 +5,8 @@
# Copyright (C) 2013 Invitu <contact@invitu.com>
#
# 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,
@ -25,7 +25,7 @@
"author": "INVITU",
"website": "http://www.invitu.com",
"license": "AGPL-3",
"category": "",
"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.

23
asterisk_click2dial_registration/asterisk_click2dial_registration.py

@ -5,8 +5,8 @@
# Copyright (C) 2013 Invitu <contact@invitu.com>
#
# 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)

4
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)

23
base_phone/__init__.py

@ -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

55
base_phone/__openerp__.py

@ -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,
}

120
base_phone/base_phone.py

@ -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)

50
base_phone/res_partner_view.xml

@ -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
asterisk_click2dial/static/lib/js/PhoneFormat.js → base_phone/static/lib/js/PhoneFormat.js

14
asterisk_click2dial/static/src/js/phone_widget.js → base_phone/static/src/js/phone_widget.js

@ -1,11 +1,11 @@
// Base phone module for OpenERP
// Copyright (C) 2013 Alexis de Lattre <alexis@via.ecp.fr>
// Copyright (C) 2013-2014 Alexis de Lattre <alexis@via.ecp.fr>
// 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');
}

0
asterisk_click2dial/static/src/xml/phone.xml → base_phone/static/src/xml/phone.xml

22
base_phone/wizard/__init__.py

@ -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

100
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 <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

10
asterisk_click2dial/wizard/reformat_all_phonenumbers_view.xml → base_phone/wizard/reformat_all_phonenumbers_view.xml

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Asterisk Click2dial module for OpenERP
Base Phone module for OpenERP
Copyright (C) 2012-2013 Alexis de Lattre <alexis@via.ecp.fr>
The licence is in the file __openerp__.py
-->
@ -30,15 +30,17 @@
</record>
<record id="reformat_all_phonenumbers_action" model="ir.actions.act_window">
<field name="name">Reformat all phone numbers</field>
<field name="name">Reformat Phone Numbers</field>
<field name="res_model">reformat.all.phonenumbers</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<!-- Menu entry under Settings > Configuration -->
<menuitem id="reformat_all_phonenumbers_menu" action="reformat_all_phonenumbers_action" parent="menu_asterisk_servers" sequence="100"/>
<!-- Menu entry under Settings > Technical -->
<menuitem id="menu_config_phone" name="Phone" parent="base.menu_custom"/>
<menuitem id="reformat_all_phonenumbers_menu" action="reformat_all_phonenumbers_action" parent="menu_config_phone" sequence="100"/>
</data>
Loading…
Cancel
Save