profile: format phone numbers at cell-rendering time (#72769) #23
|
@ -24,6 +24,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from combo.data.library import register_cell_class
|
||||
from combo.data.models import JsonCellBase
|
||||
from combo.profile import utils as profile_utils
|
||||
|
||||
|
||||
class Profile(models.Model):
|
||||
|
@ -61,6 +62,8 @@ class ProfileCell(JsonCellBase):
|
|||
if value:
|
||||
if attribute['kind'] in ('birthdate', 'date'):
|
||||
value = parse_date(value)
|
||||
if attribute['kind'] == 'phone_number':
|
||||
value = profile_utils.get_formatted_phone(value)
|
||||
extra_context['profile_fields'][attribute['name']]['value'] = value
|
||||
else:
|
||||
extra_context['error'] = 'unknown user'
|
||||
|
|
|
@ -14,8 +14,10 @@
|
|||
# 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/>.
|
||||
|
||||
import phonenumbers
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from phonenumbers.phonenumberutil import region_code_for_country_code
|
||||
|
||||
if 'mellon' in settings.INSTALLED_APPS:
|
||||
from mellon.models import UserSAMLIdentifier
|
||||
|
@ -46,3 +48,29 @@ def get_user_from_name_id(name_id, raise_on_missing=False):
|
|||
if raise_on_missing:
|
||||
raise User.DoesNotExist()
|
||||
return ProxiedUser(name_id=name_id)
|
||||
|
||||
|
||||
def get_formatted_phone(value, country_code=None):
|
||||
if country_code is None:
|
||||
country_code = settings.DEFAULT_COUNTRY_CODE
|
||||
|
||||
|
||||
region_code = 'ZZ' # phonenumbers' default value for unknown regions
|
||||
try:
|
||||
region_code = region_code_for_country_code(int(country_code))
|
||||
except ValueError:
|
||||
pass
|
||||
if region_code == 'ZZ':
|
||||
return value
|
||||
|
||||
try:
|
||||
pn = phonenumbers.parse(value, region_code)
|
||||
except phonenumbers.NumberParseException:
|
||||
return value
|
||||
|
||||
if not phonenumbers.is_valid_number(pn):
|
||||
return value
|
||||
|
||||
if country_code == str(pn.country_code):
|
||||
return phonenumbers.format_number(pn, phonenumbers.PhoneNumberFormat.NATIONAL)
|
||||
|
||||
return phonenumbers.format_number(pn, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
|
||||
Ghost
commented
phonenumbers.PhoneNumberFormat.INTERNATIONAL serait plus joli (+221 77 643 93 28) phonenumbers.PhoneNumberFormat.INTERNATIONAL serait plus joli (+221 77 643 93 28)
pmarillonnet
commented
Ok, je n’avais pas réalisé que ces deux formats différaient, my bad. C’est corrigé et c’est mieux ainsi, en effet. Ok, je n’avais pas réalisé que ces deux formats différaient, my bad. C’est corrigé et c’est mieux ainsi, en effet.
|
||||
|
|
|
@ -377,6 +377,9 @@ CATEGORIES_CELL_ENABLED = False
|
|||
# and enable others
|
||||
CHART_FILTERS_CELL_ENABLED = True
|
||||
|
||||
# default country code for phonenumbers' user phone parsing
|
||||
DEFAULT_COUNTRY_CODE = '33'
|
||||
|
||||
|
||||
def debug_show_toolbar(request):
|
||||
from debug_toolbar.middleware import show_toolbar as dt_show_toolbar # pylint: disable=import-error
|
||||
|
|
1
setup.py
1
setup.py
|
@ -181,6 +181,7 @@ setup(
|
|||
'pywebpush',
|
||||
'pygal',
|
||||
'lxml',
|
||||
'phonenumbers',
|
||||
],
|
||||
zip_safe=False,
|
||||
cmdclass={
|
||||
|
|
|
@ -105,6 +105,12 @@ USER_PROFILE_CONFIG = {
|
|||
'label': 'Birth Date',
|
||||
'user_visible': True,
|
||||
},
|
||||
{
|
||||
'name': 'phone',
|
||||
'kind': 'phone_number',
|
||||
'label': 'Phone',
|
||||
'user_visible': True,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -121,3 +127,5 @@ REST_FRAMEWORK = {
|
|||
'rest_framework.authentication.BasicAuthentication',
|
||||
]
|
||||
}
|
||||
|
||||
DEFAULT_COUNTRY_CODE = '33'
|
||||
|
|
|
@ -20,7 +20,11 @@ def test_profile_cell(requests_get, app, admin_user):
|
|||
cell = ProfileCell(page=page, order=0)
|
||||
cell.save()
|
||||
|
||||
data = {'first_name': 'Foo', 'birthdate': '2018-08-10'}
|
||||
data = {
|
||||
'first_name': 'Foo',
|
||||
'birthdate': '2018-08-10',
|
||||
'phone': '+33612345678',
|
||||
}
|
||||
requests_get.return_value = mock.Mock(content=json.dumps(data), json=lambda: data, status_code=200)
|
||||
|
||||
admin_user.get_name_id = lambda: '123456'
|
||||
|
@ -28,4 +32,17 @@ def test_profile_cell(requests_get, app, admin_user):
|
|||
context = cell.get_cell_extra_context({'synchronous': True, 'selected_user': admin_user})
|
||||
assert context['profile_fields']['first_name']['value'] == 'Foo'
|
||||
assert context['profile_fields']['birthdate']['value'] == datetime.date(2018, 8, 10)
|
||||
assert context['profile_fields']['phone']['value'] == '06 12 34 56 78'
|
||||
assert requests_get.call_args[0][0] == 'http://example.org/api/users/123456/'
|
||||
|
||||
# foreign number remains in its international representation
|
||||
data['phone'] = '+221 33 889 00 00' # Dakar landline number
|
||||
requests_get.return_value = mock.Mock(content=json.dumps(data), json=lambda: data, status_code=200)
|
||||
context = cell.get_cell_extra_context({'synchronous': True, 'selected_user': admin_user})
|
||||
Ghost
commented
Ajouter un test qui montre qu'un numéro genre en +221 s'affiche bien avec son indicatif international ? Ajouter un test qui montre qu'un numéro genre en +221 s'affiche bien avec son indicatif international ?
|
||||
assert context['profile_fields']['phone']['value'] == '+221 33 889 00 00' # international representation
|
||||
|
||||
# erroneous number is not parsed at all
|
||||
data['phone'] = '+336a23c5678'
|
||||
requests_get.return_value = mock.Mock(content=json.dumps(data), json=lambda: data, status_code=200)
|
||||
context = cell.get_cell_extra_context({'synchronous': True, 'selected_user': admin_user})
|
||||
assert context['profile_fields']['phone']['value'] == '+336a23c5678'
|
||||
|
|
Loading…
Reference in New Issue
On devrait quand même poser un « DEFAULT_COUNTRY_CODE = '33" » dans combo/settings.py (pour ne pas avoir de code qui fasse appel à un settings inexistant, combo devrait pouvoir tourner "sans hobo").