profile: format phone numbers at cell-rendering time (#72769)
gitea-wip/combo/pipeline/pr-main This commit looks good
Details
gitea-wip/combo/pipeline/pr-main This commit looks good
Details
This commit is contained in:
parent
e1046fa0b8
commit
16e6fc8711
|
@ -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)
|
||||
|
|
|
@ -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})
|
||||
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