Browse Source

Merge pull request #190 from akretion/12-up-port

[12.0] Forward port dial button refactor from v11 to v12
pull/191/head
Alexis de Lattre 6 years ago
committed by GitHub
parent
commit
f16cf685ac
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      asterisk_click2dial/__manifest__.py
  2. 2
      asterisk_click2dial/demo/asterisk_click2dial_demo.xml
  3. 28
      asterisk_click2dial/static/src/js/asterisk_click2dial.js
  4. 10
      asterisk_click2dial/views/asterisk_server.xml
  5. 2
      base_phone/common.py
  6. 2
      base_phone/fields.py
  7. 10
      base_phone/models/phone_common.py
  8. 5
      base_phone/models/phone_validation_mixin.py
  9. 3
      base_phone/models/res_config_settings.py
  10. 20
      base_phone/models/res_partner.py
  11. 156
      base_phone/static/src/js/phone_widget.js
  12. 3
      base_phone/tests/__init__.py
  13. 69
      base_phone/tests/test_phone.py
  14. 20
      base_phone/views/res_config_settings.xml
  15. 5
      base_phone/wizard/reformat_all_phonenumbers.py
  16. 2
      base_phone_popup/__init__.py
  17. 38
      base_phone_popup/__manifest__.py
  18. 4
      base_phone_popup/models/__init__.py
  19. 46
      base_phone_popup/models/phone_common.py
  20. 13
      base_phone_popup/models/res_users.py
  21. 1
      base_phone_popup/readme/CONTRIBUTORS.rst
  22. 3
      base_phone_popup/readme/DESCRIPTION.rst
  23. 1
      base_phone_popup/readme/USAGE.rst
  24. 7
      base_phone_popup/views/res_users.xml
  25. 82
      crm_phone/tests/test_crm_phone.py
  26. 5
      crm_phone/wizard/create_crm_phonecall.py
  27. 4
      hr_recruitment_phone/__manifest__.py
  28. 3
      oca_dependencies.txt

4
asterisk_click2dial/__manifest__.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2010-2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2010-2019 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{

2
asterisk_click2dial/demo/asterisk_click2dial_demo.xml

@ -17,7 +17,7 @@
<field name="company_id" ref="base.main_company" />
</record>
<record id="base.user_root" model="res.users">
<record id="base.user_admin" model="res.users">
<field name="internal_number">11</field>
<field name="resource">11</field>
<field name="callerid">Administrator &lt;0141981242&gt;</field>

28
asterisk_click2dial/static/src/js/asterisk_click2dial.js

@ -7,12 +7,18 @@ odoo.define('asterisk_click2dial.systray.OpenCaller', function (require) {
var core = require('web.core');
var SystrayMenu = require('web.SystrayMenu');
var web_client = require('web.web_client');
var Widget = require('web.Widget');
var _t = core._t;
var click2dial = {};
var FieldPhone = require('base_phone.updatedphone_widget').FieldPhone;
FieldPhone.include({
showDialButton: function () {
return true;
}
});
var OpenCallerMenu = Widget.extend({
@ -22,10 +28,6 @@ var OpenCallerMenu = Widget.extend({
'click': 'on_open_caller',
},
start: function () {
this._super();
},
on_open_caller: function (event) {
event.stopPropagation();
var self = this;
@ -33,14 +35,14 @@ var OpenCallerMenu = Widget.extend({
self._rpc({
route: '/asterisk_click2dial/get_record_from_my_channel',
params: {local_context: context, },
}).done(function(r) {
}).then(function(r) {
// console.log('RESULT RPC r='+r);
// console.log('RESULT RPC type r='+typeof r);
// console.log('RESULT RPC isNaN r='+isNaN(r));
if (r === false) {
self.do_warn(
_t('Failure'),
_t('Problem in the connection to Asterisk'),
_t('IPBX error'),
_t('Calling party number not retreived from IPBX or IPBX unreachable by Odoo'),
false);
}
else if (typeof r == 'string' && isNaN(r)) {
@ -59,13 +61,13 @@ var OpenCallerMenu = Widget.extend({
target: 'new',
context: {'default_calling_number': r},
};
web_client.action_manager.do_action(action);
self.do_action(action);
}
else if (typeof r == 'object' && r.length == 3) {
self.do_notify(
_t('Success'),
_.str.sprintf(_t('Moving to %s ID %d'), r[0], r[1]),
_.str.sprintf(_t("On the phone with '%s'"), r[2]),
_.str.sprintf(_t("Moving to form view of '%s' (%s ID %d)"), r[2], r[0], r[1]),
false);
var action = {
type: 'ir.actions.act_window',
@ -83,7 +85,7 @@ var OpenCallerMenu = Widget.extend({
target: 'current',
context: {},
};
web_client.action_manager.do_action(action);
self.do_action(action);
}
});
},

10
asterisk_click2dial/views/asterisk_server.xml

@ -14,6 +14,8 @@
<search string="Asterisk Server Search">
<field name="name"
filter_domain="['|', ('name', 'ilike', self), ('ip_address', 'ilike', self)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
</search>
</field>
</record>
@ -24,6 +26,13 @@
<field name="arch" type="xml">
<form string="Asterisk Servers">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
</button>
</div>
<div class="oe_title">
<label for="name" string="Server Name" class="oe_edit_only"/>
<h1>
@ -33,7 +42,6 @@
<group name="main">
<field name="company_id"
groups="base.group_multi_company"/>
<field name="active" />
</group>
<group name="ami" string="Asterisk Manager Interface">
<field name="ip_address" />

2
base_phone/common.py

@ -25,7 +25,7 @@ def convert_phone_field(value, country_code):
new_value = phonenumbers.format_number(
res_parse, phonenumbers.PhoneNumberFormat.E164)
_logger.debug('new_value=%s', new_value)
except:
except Exception:
_logger.error(
"Cannot reformat the phone number '%s' to "
"international format with region=%s",

2
base_phone/fields.py

@ -51,7 +51,7 @@ class Fax(fields.Char):
res_parse, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
no_break_space = u'\u00A0'
res = res.replace(' ', no_break_space)
except:
except Exception:
pass
# print 'cache value', res
return res

10
base_phone/models/phone_common.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2010-2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2010-2018 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, api
@ -68,12 +68,12 @@ class PhoneCommon(models.AbstractModel):
_logger.debug("get_record_from_phone_number sql=%s", sql)
self._cr.execute(sql, tuple(sql_args))
res_sql = self._cr.fetchall()
#res_obj = obj.search(domain)
if len(res_sql) > 1:
res_ids = [x[0] for x in res_sql]
_logger.warning(
u"There are several %s (IDS = %s) with a phone number "
"ending with '%s'. Taking the first one.",
obj._name, res_obj.ids, end_number_to_match)
obj._name, res_ids, end_number_to_match)
if res_sql:
obj_id = res_sql[0][0]
res_obj = obj.browse(obj_id)
@ -96,7 +96,7 @@ class PhoneCommon(models.AbstractModel):
senv = False
try:
senv = self.with_context(callerid=True).env[model_name]
except:
except Exception:
continue
if (
hasattr(senv, '_phone_name_sequence') and

5
base_phone/models/phone_validation_mixin.py

@ -13,6 +13,9 @@ class PhoneValidationMixin(models.AbstractModel):
def _phone_get_country(self):
if 'country_id' in self and self.country_id:
return self.country_id
if 'partner_id' in self and self.partner_id and self.partner_id.country_id:
if (
'partner_id' in self and
self.partner_id and
self.partner_id.country_id):
return self.partner_id.country_id
return self.env.user.company_id.country_id

3
base_phone/models/res_config_settings.py

@ -9,4 +9,5 @@ class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
number_of_digits_to_match_from_end = fields.Integer(
related='company_id.number_of_digits_to_match_from_end')
related='company_id.number_of_digits_to_match_from_end',
readonly=False)

20
base_phone/models/res_partner.py

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright 2016-2018 Akretion France
# Copyright 2016-2019 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
from odoo import api, models
class ResPartner(models.Model):
@ -28,3 +27,18 @@ class ResPartner(models.Model):
return res
else:
return super(ResPartner, self).name_get()
# These 2 onchange have the same name (and same code) than in the
# module crm_phone_validation ; but we don't depend on that module
# because we don't want base_phone to depend on crm.
# When both base_phone AND crm_phone_validation are installed,
# as the methods have the same name, only one of the 2 will be executed
@api.onchange('phone', 'country_id', 'company_id')
def _onchange_phone_validation(self):
if self.phone:
self.phone = self.phone_format(self.phone)
@api.onchange('mobile', 'country_id', 'company_id')
def _onchange_mobile_validation(self):
if self.mobile:
self.mobile = self.phone_format(self.mobile)

156
base_phone/static/src/js/phone_widget.js

@ -8,97 +8,91 @@ odoo.define('base_phone.updatedphone_widget', function (require) {
var core = require('web.core');
var web_client = require('web.web_client');
var basicFields = require('web.basic_fields');
var InputField = basicFields.InputField;
var originalFieldPhone = basicFields.FieldPhone;
var fieldRegistry = require('web.field_registry');
var QWeb = core.qweb;
var FieldPhone = require('web.basic_fields').FieldPhone;
var _t = core._t;
var updatedFieldPhone = originalFieldPhone.extend({
FieldPhone.include({
/* init: function () {
this._super.apply(this, arguments);
}, */
/* Always enable phone link tel:, not only on small screens */
_canCall: function () {
return true;
},
showDialButton: function () {
// must be inherited by ipbx specific modules
// and set to true
return false;
},
_renderReadonly: function() {
// create a link to trigger action on server
// this link will be after the <a href="tel:">
this._super();
if (this.mode == "readonly") {
var self = this;
var phone_num = this.value;
/* if(phone_num) {
phone_num = phone_num.replace(/ /g, '').replace(/-/g, '');
} */
/* var click2dial_text = '';
if (phone_num && !this.options.dial_button_invisible) {
click2dial_text = _t('Dial');
}
this.$el.filter('#click2dial').off('click');
this.$el.filter('#click2dial')
.text(click2dial_text)
.attr('href', '#')
} */
this.$el.filter('a[href^="tel:"]').off('click');
this.$el.filter('a[href^="tel:"]')
.on('click', function(ev) {
self.do_notify(
_t('Click2dial started'),
_t('Unhook your ringing phone'),
false);
var arg = {
'phone_number': phone_num,
'click2dial_model': self.model,
'click2dial_id': self.res_id};
self._rpc({
route: '/base_phone/click2dial',
params: arg,
}).done(function(r) {
// TODO: check why it never goes in there
if (r === false) {
self.do_warn("Click2dial failed");
} else if (typeof r === 'object') {
self.do_notify(
_t('Click2dial successfull'),
_t('Number dialed:') + ' ' + r.dialed_number,
false);
if (r.action_model) {
var context = {
'click2dial_model': self.model,
'click2dial_id': self.res_id,
'phone_number': phone_num,
};
var action = {
name: r.action_name,
type: 'ir.actions.act_window',
res_model: r.action_model,
view_mode: 'form',
views: [[false, 'form']],
target: 'new',
context: context,
};
this.do_action(action);
}
}
});
});
if (!this.showDialButton()) {
return;
}
}
});
var self = this;
// To avoid conflicts, we check that widgets do not exist before using
/*
if(!core.form_widget_registry.get('fax')){
core.form_widget_registry.add('fax', FieldFax);
}
// create our link
var dial = $('<a href="#" class="dial"><div class="label label-primary">☎ Dial</div></a>');
if(!core.form_widget_registry.get('phone')){
core.form_widget_registry.add('phone', FieldPhone);
}
*/
// add a parent element
// it's not possible to append to $el directly
// because $el don't have any parent yet
var parent = $('<div>');
parent.append([this.$el[0], ' ', dial]);
fieldRegistry.add('phone', updatedFieldPhone);
// replace this.$el by our new container
this.$el = parent;
return updatedFieldPhone;
var phone_num = this.value;
dial.click(function(evt) {
self.click2dial(phone_num);
});
},
click2dial: function(phone_num) {
var self = this;
this.do_notify(
_.str.sprintf(_t('Click2dial to %s'), phone_num),
_t('Unhook your ringing phone'),
false);
var params = {
'phone_number': phone_num,
'click2dial_model': this.model,
'click2dial_id': this.res_id};
return this._rpc({
route: '/base_phone/click2dial',
params: params,
}).then(function(r) {
console.log('successfull', r);
if (r === false) {
self.do_warn("Click2dial failed");
} else if (typeof r === 'object') {
self.do_notify(
_t('Click2dial successfull'),
_.str.sprintf(_t('Number dialed: %s'), r.dialed_number),
false);
if (r.action_model) {
var action = {
name: r.action_name,
type: 'ir.actions.act_window',
res_model: r.action_model,
view_mode: 'form',
views: [[false, 'form']],
target: 'new',
context: params,
};
return self.do_action(action);
}
}
}, function (r) {
console.log('on error');
self.do_warn("Click2dial failed");
});
}
});
return {
'FieldPhone': FieldPhone
};
});

3
base_phone/tests/__init__.py

@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
from . import test_phone

69
base_phone/tests/test_phone.py

@ -1,69 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2016-2018 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
class TestPhone(TransactionCase):
def test_phone(self):
company = self.env.ref('base.main_company')
fr_country_id = self.env.ref('base.fr').id
company.country_id = fr_country_id
rpo = self.env['res.partner']
# Create an existing partner without country
partner1 = rpo.create({
'name': u'Pierre Paillet',
'phone': '04-72-08-87-32',
'mobile': '06.42.77.42.66',
'fax': '(0) 1 45 42 12 42',
})
self.assertEquals(partner1.phone, u'+33 4 72 08 87 32')
self.assertEquals(partner1.mobile, u'+33 6 42 77 42 66')
self.assertEquals(partner1.fax, u'+33 1 45 42 12 42')
# Create a partner with country
self.env.ref('base.res_partner_12').country_id =\
self.env.ref('base.ch').id
partner2 = rpo.create({
'name': u'Joël Grand-Guillaume',
'parent_id': self.env.ref('base.res_partner_12').id,
'phone': '(0) 21 619 10 10',
'mobile': '(0) 79 606 42 42',
})
self.assertEquals(partner2.country_id, self.env.ref('base.ch'))
self.assertEquals(partner2.phone, u'+41 21 619 10 10')
self.assertEquals(partner2.mobile, u'+41 79 606 42 42')
# Write on an existing partner
agrolait = self.env.ref('base.res_partner_2')
self.assertEquals(agrolait.country_id, self.env.ref('base.be'))
agrolait.write({'phone': '(0) 2 391 43 74'})
self.assertEquals(agrolait.phone, u'+32 2 391 43 74')
# Write on an existing partner with country at the same time
agrolait.write({
'fax': '04 72 89 32 43',
'country_id': fr_country_id,
})
self.assertEquals(agrolait.fax, u'+33 4 72 89 32 43')
# Write an invalid phone number
partner2.fax = '42'
self.assertEquals(partner2.fax, u'42')
# Test get_name_from_phone_number
pco = self.env['phone.common']
name = pco.get_name_from_phone_number('0642774266')
self.assertEquals(name, 'Pierre Paillet')
name2 = pco.get_name_from_phone_number('0041216191010')
self.assertEquals(name2, u'Joël Grand-Guillaume (Camptocamp)')
# Test against the POS bug
# https://github.com/OCA/connector-telephony/issues/113
# When we edit/create a partner from the POS,
# the country_id key in create(vals) is given as a string !
partnerpos = rpo.create({
'name': u'POS customer',
'phone': '04-72-08-87-42',
'country_id': str(fr_country_id),
})
self.assertEquals(partnerpos.phone, u'+33 4 72 08 87 42')
self.assertEquals(partnerpos.country_id.id, fr_country_id)

20
base_phone/views/res_config_settings.xml

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014-2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
Copyright 2014-2018 Akretion France (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
@ -12,13 +13,16 @@
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<div id="phone" string="Phone">
<h2>Phone</h2>
<div class="row mt16 o_settings_container">
<label for="number_of_digits_to_match_from_end"/>
<div>
<field name="number_of_digits_to_match_from_end" class="oe_inline"/>
<xpath expr="//div[@name='integration']" position="after">
<h2>Phone</h2>
<div class="row mt16 o_settings_container" id="phone">
<div class="col-xs-12 col-md-12 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="row mt16">
<label for="number_of_digits_to_match_from_end" class="col-md-4 o_light_label"/>
<field name="number_of_digits_to_match_from_end"/>
</div>
</div>
</div>
</div>

5
base_phone/wizard/reformat_all_phonenumbers.py

@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Copyright 2012-2018 Akretion France
# Copyright 2012-2019 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api
from odoo import models, fields
import logging
logger = logging.getLogger(__name__)

2
base_phone_popup/__init__.py

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
from . import popup
from . import models

38
base_phone_popup/__manifest__.py

@ -1,43 +1,15 @@
# -*- coding: utf-8 -*-
# © 2014-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2014-2019 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Base Phone Pop-up',
'version': '9.0.1.0.0',
'version': '12.0.1.0.0',
'category': 'Phone',
'license': 'AGPL-3',
'summary': 'Pop-up the related form view to the user on incoming calls',
'description': """
Base Phone Pop-up
=================
When the user receives a phone call, OpenERP can automatically open the
corresponding partner/lead/employee/... in a pop-up without any action from the
user.
The module *web_action_request* can be downloaded with Mercurial:
hg clone http://bitbucket.org/anybox/web_action_request
It depends on 2 other modules, *web_longpolling* and *web_socketio*, that can
be downloaded with this command:
hg clone http://bitbucket.org/anybox/web_socketio
You will find some hints in this documentation :
https://bitbucket.org/anybox/web_action_request
Warning : proxying WebSockets is only supported since Nginx 1.3.13 ; the
feature provided by this module won't work with older versions of Nginx.
TODO : document this new feature on the Akretion Web site :
http://www.akretion.com/products-and-services/openerp-asterisk-voip-connector
""",
'author': "Akretion,Odoo Community Association (OCA)",
'website': 'http://www.akretion.com/',
'depends': ['base_phone', 'web_action_request'],
'data': ['res_users_view.xml'],
'installable': False,
'depends': ['base_phone', 'web_notify'],
'installable': True,
}

4
base_phone_popup/models/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import phone_common
#from . import res_users

46
base_phone_popup/popup.py → base_phone_popup/models/phone_common.py

@ -1,11 +1,12 @@
# -*- coding: utf-8 -*-
# © 2014-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2014-2018 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
from odoo import api, models, _
from odoo.addons.web.controllers.main import clean_action
import logging
logger = logging.getLogger(__name__)
@ -22,8 +23,8 @@ class PhoneCommon(models.AbstractModel):
'type': 'ir.actions.act_window',
'res_model': record_res[0],
'view_mode': 'form,tree',
'views': [[False, 'form']], # Beurk, but needed
'target': 'new',
'views': [[False, 'form']],
# 'target': 'new',
'res_id': record_res[1],
}
else:
@ -32,8 +33,8 @@ class PhoneCommon(models.AbstractModel):
'type': 'ir.actions.act_window',
'res_model': 'number.not.found',
'view_mode': 'form',
'views': [[False, 'form']], # Beurk, but needed
'target': 'new',
'views': [[False, 'form']],
# 'target': 'new',
'context': {'default_calling_number': number}
}
return action
@ -44,26 +45,29 @@ class PhoneCommon(models.AbstractModel):
res = self.get_record_from_phone_number(number)
users = self.env['res.users'].search(
[('login', 'in', login_list)])
logger.debug(
'Notify incoming call from number %s to users %s'
logger.info(
'Notify incoming call from number %s to user IDs %s'
% (number, users.ids))
action = self._prepare_incall_pop_action(res, number)
action = clean_action(action)
if action:
for user in users:
if user.context_incall_popup:
self.sudo(user.id).env['action.request'].notify(action)
logger.debug(
'This action has been sent to user ID %d: %s'
% (user.id, action))
channel = 'notify_info_%s' % user.id
bus_message = {
'message': _('Here is my message'),
'title': _('Incoming call'),
'action': action,
# 'sticky': True,
'action_link_name': 'action_link_name',
}
self.sudo().env['bus.bus'].sendone(
channel, bus_message)
logger.debug(
'This action has been sent to user ID %d: %s'
% (user.id, action))
if res:
callerid = res[2]
else:
callerid = False
return callerid
class ResUsers(models.Model):
_inherit = 'res.users'
context_incall_popup = fields.Boolean(
string='Pop-up on Incoming Calls', default=True)

13
base_phone_popup/models/res_users.py

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright 2014-2018 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResUsers(models.Model):
_inherit = 'res.users'
context_incall_popup = fields.Boolean(
string='Pop-up on Incoming Calls', default=True)

1
base_phone_popup/readme/CONTRIBUTORS.rst

@ -0,0 +1 @@
* Alexis de Lattre <alexis.delattre@akretion.com>

3
base_phone_popup/readme/DESCRIPTION.rst

@ -0,0 +1,3 @@
When the user receives a phone call, Odoo will display a notification
at the top-right of the screen that contains a link to the corresponding
partner/lead/employee/... or a link to the *Number not found* wizard.

1
base_phone_popup/readme/USAGE.rst

@ -0,0 +1 @@
To deploy this feature with an Asterisk-based IPBX, please read this `document <https://akretion.com/en/open-source-contributions/odoo-asterisk-voip-connector>`_.

7
base_phone_popup/res_users_view.xml → base_phone_popup/views/res_users.xml

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2014-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
Copyright 2014-2018 Akretion France
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<data>
<record id="view_users_form" model="ir.ui.view">
<field name="name">base_phone_popup.res.users.form</field>
@ -35,5 +36,5 @@
</field>
</record>
</data>
</odoo>

82
crm_phone/tests/test_crm_phone.py

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2016-2018 Akretion France
# Copyright 2016-2019 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
@ -8,6 +7,71 @@ from odoo.tests.common import TransactionCase
class TestCRMPhone(TransactionCase):
def test_phone(self):
company = self.env.ref('base.main_company')
fr_country_id = self.env.ref('base.fr').id
company.country_id = fr_country_id
rpo = self.env['res.partner']
# Create an existing partner without country
partner1 = rpo.create({
'name': 'Pierre Paillet',
'phone': '04-72-08-87-32',
'mobile': '06.42.77.42.66',
})
partner1._onchange_phone_validation()
partner1._onchange_mobile_validation()
self.assertEquals(partner1.phone, '+33 4 72 08 87 32')
self.assertEquals(partner1.mobile, '+33 6 42 77 42 66')
# Create a partner with country
parent_partner2 = rpo.create({
'name': 'C2C',
'country_id': self.env.ref('base.ch').id,
})
partner2 = rpo.create({
'name': 'Joël Grand-Guillaume',
'parent_id': parent_partner2.id,
'phone': '(0) 21 619 10 10',
'mobile': '(0) 79 606 42 42',
})
partner2._onchange_phone_validation()
partner2._onchange_mobile_validation()
self.assertEquals(partner2.country_id, self.env.ref('base.ch'))
self.assertEquals(partner2.phone, '+41 21 619 10 10')
self.assertEquals(partner2.mobile, '+41 79 606 42 42')
# Write on an existing partner
partner3 = rpo.create({
'name': 'Belgian corp',
'country_id': self.env.ref('base.be').id,
})
partner3.write({'phone': '(0) 2 391 43 74'})
partner3._onchange_phone_validation()
self.assertEquals(partner3.phone, '+32 2 391 43 74')
# Write on an existing partner with country at the same time
partner3.write({
'phone': '04 72 89 32 43',
'country_id': fr_country_id,
})
partner3._onchange_phone_validation()
self.assertEquals(partner3.phone, '+33 4 72 89 32 43')
# Test get_name_from_phone_number
pco = self.env['phone.common']
name = pco.get_name_from_phone_number('0642774266')
self.assertEquals(name, 'Pierre Paillet')
name2 = pco.get_name_from_phone_number('0041216191010')
self.assertEquals(name2, 'C2C, Joël Grand-Guillaume')
# Test against the POS bug
# https://github.com/OCA/connector-telephony/issues/113
# When we edit/create a partner from the POS,
# the country_id key in create(vals) is given as a string !
partnerpos = rpo.create({
'name': 'POS customer',
'phone': '04-72-08-87-42',
'country_id': str(fr_country_id),
})
partnerpos._onchange_phone_validation()
self.assertEquals(partnerpos.phone, '+33 4 72 08 87 42')
self.assertEquals(partnerpos.country_id.id, fr_country_id)
def test_crm_phone(self):
clo = self.env['crm.lead']
lead1 = clo.create({
@ -18,23 +82,23 @@ class TestCRMPhone(TransactionCase):
'country_id': self.env.ref('base.fr').id,
})
lead1._onchange_mobile_validation()
self.assertEquals(lead1.mobile, u'+33 6 42 77 42 77')
self.assertEquals(lead1.mobile, '+33 6 42 77 42 77')
lead2 = clo.create({
'name': u'Automobile Odoo deployment',
'partner_name': u'Kia',
'contact_name': u'Mikaël Content',
'name': 'Automobile Odoo deployment',
'partner_name': 'Kia',
'contact_name': 'Mikaël Content',
'country_id': self.env.ref('base.ch').id,
'phone': '04 31 23 45 67',
})
lead2._onchange_phone_validation()
self.assertEquals(lead2.phone, u'+41 43 123 45 67')
self.assertEquals(lead2.phone, '+41 43 123 45 67')
lead3 = clo.create({
'name': 'Angela Strasse',
'country_id': self.env.ref('base.de').id,
'phone': '08912345678',
})
lead3._onchange_phone_validation()
self.assertEquals(lead3.phone, u'+49 89 12345678')
self.assertEquals(lead3.phone, '+49 89 12345678')
partner4 = self.env['res.partner'].create({
'name': 'Belgian Guy',
'country_id': self.env.ref('base.be').id,
@ -45,7 +109,7 @@ class TestCRMPhone(TransactionCase):
'mobile': '(0) 2-391-43-75',
})
lead4._onchange_mobile_validation()
self.assertEquals(lead4.mobile, u'+32 2 391 43 75')
self.assertEquals(lead4.mobile, '+32 2 391 43 75')
pco = self.env['phone.common']
name = pco.get_name_from_phone_number('0642774277')
self.assertEquals(name, 'Jacques Toufaux (Ford)')

5
crm_phone/wizard/create_crm_phonecall.py

@ -30,15 +30,12 @@ class WizardCreateCrmPhonecall(models.TransientModel):
'default_direction': direction,
'default_team_id': teams and teams[0].id or False,
})
domain = False
if self.env.context.get('click2dial_model') == 'res.partner':
partner_id = self.env.context.get('click2dial_id')
action_ctx['default_partner_id'] = partner_id
domain = [('partner_id', 'child_of', partner_id)]
elif self.env.context.get('click2dial_model') == 'crm.lead':
lead_id = self.env.context.get('click2dial_id')
action_ctx['default_opportunity_id'] = lead_id
domain = [('opportunity_id', '=', lead_id)]
parsed_num = phonenumbers.parse(self.env.context.get('phone_number'))
number_type = phonenumbers.number_type(parsed_num)
if number_type == 1:
@ -50,8 +47,8 @@ class WizardCreateCrmPhonecall(models.TransientModel):
action = self.env['ir.actions.act_window'].for_xml_id(
'crm_phone', 'crm_phonecall_action')
action.update({
'domain': domain,
'view_mode': 'form,tree,calendar',
'views': False,
'context': action_ctx,
})
return action

4
hr_recruitment_phone/__manifest__.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2014-2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# Copyright 2014-2019 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{

3
oca_dependencies.txt

@ -1 +1,2 @@
server-tools
server-tools
web
Loading…
Cancel
Save