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 10 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. 32
      asterisk_click2dial_crm/__openerp__.py
  8. 31
      asterisk_click2dial_crm/asterisk_click2dial_crm.py
  9. 6
      asterisk_click2dial_crm/wizard/__init__.py
  10. 35
      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. 8
      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. 16
      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

32
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,
@ -27,28 +27,24 @@
"version": "0.1",
"author": "Zikzakmedia SL, Akretion",
"website": "http://www.zikzakmedia.com",
"license" : "AGPL-3",
"license": "AGPL-3",
"category": "Customer Relationship Management",
"description": """
This module adds CRM-specific features to the asterisk_click2dial module.
Asterisk Click2dial CRM
=======================
It adds 2 features :
This module adds CRM-specific features to the asterisk_click2dial module.
First, when you do a click2dial, OpenERP will propose you to create an
outbound phone call in the CRM ; if you answer 'Yes', it will create the phone
call in the CRM and open it in a new tab. If some users don't want to be asked
to create a phone call in the CRM each time they do a click2dial, you
should disable the corresponding option in the 'Telephony' tab of the 'User'
form.
It adds 2 features :
Second, when you receive a phone call and run the wizard "Open calling partner",
if the partner is found in OpenERP, you will see a button that proposes to create
an inbound phone call in the CRM.
First, when you do a click2dial, OpenERP will propose you to create an outbound phone call in the CRM ; if you answer 'Yes', it will create the phone call in the CRM and open it in a new tab. If some users don't want to be asked to create a phone call in the CRM each time they do a click2dial, you should disable the corresponding option in the 'Telephony' tab of the 'User' form.
This module has been initially developped by Zikzakmedia and has been enhanced by Akretion.
Second, when you receive a phone call and run the wizard "Open calling partner", if the partner is found in OpenERP, you will see a button that proposes to create an inbound phone call in the CRM.
A detailed documentation for the OpenERP-Asterisk connector is available on the Akretion Web site : http://www.akretion.com/en/products-and-services/openerp-asterisk-voip-connector
""",
This module has been initially developped by Zikzakmedia and has been enhanced by Akretion.
A detailed documentation for the OpenERP-Asterisk connector is available on the Akretion Web site : http://www.akretion.com/en/products-and-services/openerp-asterisk-voip-connector
""",
"depends": [
'asterisk_click2dial',
'crm',

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,

35
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 {
@ -53,19 +58,19 @@ class wizard_create_crm_phonecall(orm.TransientModel):
'view_type': 'form',
'view_mode': 'form,tree',
'type': 'ir.actions.act_window',
'nodestroy': False, # close the pop-up wizard after action
'nodestroy': False, # close the pop-up wizard after action
'target': 'current',
'context': context,
}
class wizard_open_calling_partner(orm.TransientModel):
_inherit = "wizard.open.calling.partner"
def create_incoming_phonecall(self, cr, uid, ids, crm_categ, context=None):
'''Started by button on 'open calling partner wizard'''
partner = self.browse(cr, uid, ids[0], context=context).partner_id
action = self.pool['wizard.create.crm.phonecall']._create_open_crm_phonecall(cr, uid, partner, crm_categ='Inbound', context=context)
action = self.pool['wizard.create.crm.phonecall'].\
create_open_crm_phonecall(
cr, uid, partner, crm_categ='Inbound', context=context)
return action

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

8
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,
@ -24,8 +24,8 @@
"version": "0.1",
"author": "INVITU",
"website": "http://www.invitu.com",
"license" : "AGPL-3",
"category": "",
"license": "AGPL-3",
"category": "Extra Tools",
"description": """
This module adds a button "Open Registrations" on the "Open calling partner" wizard and a "Dial" button on the Registration form.

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

16
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