diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/phone_validation/tools | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/phone_validation/tools')
| -rw-r--r-- | addons/phone_validation/tools/__init__.py | 4 | ||||
| -rw-r--r-- | addons/phone_validation/tools/phone_validation.py | 116 |
2 files changed, 120 insertions, 0 deletions
diff --git a/addons/phone_validation/tools/__init__.py b/addons/phone_validation/tools/__init__.py new file mode 100644 index 00000000..1c27cd6e --- /dev/null +++ b/addons/phone_validation/tools/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import phone_validation diff --git a/addons/phone_validation/tools/phone_validation.py b/addons/phone_validation/tools/phone_validation.py new file mode 100644 index 00000000..813f0e4f --- /dev/null +++ b/addons/phone_validation/tools/phone_validation.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import _ +from odoo.exceptions import UserError + +import logging + +_logger = logging.getLogger(__name__) +_phonenumbers_lib_warning = False + + +try: + import phonenumbers + + def phone_parse(number, country_code): + try: + phone_nbr = phonenumbers.parse(number, region=country_code, keep_raw_input=True) + except phonenumbers.phonenumberutil.NumberParseException as e: + raise UserError(_('Unable to parse %(phone)s: %(error)s', phone=number, error=str(e))) + + if not phonenumbers.is_possible_number(phone_nbr): + raise UserError(_('Impossible number %s: probably invalid number of digits.', number)) + if not phonenumbers.is_valid_number(phone_nbr): + raise UserError(_('Invalid number %s: probably incorrect prefix.', number)) + + return phone_nbr + + def phone_format(number, country_code, country_phone_code, force_format='INTERNATIONAL', raise_exception=True): + """ Format the given phone number according to the localisation and international options. + :param number: number to convert + :param country_code: the ISO country code in two chars + :type country_code: str + :param country_phone_code: country dial in codes, defined by the ITU-T (Ex: 32 for Belgium) + :type country_phone_code: int + :param force_format: stringified version of format globals (see + https://github.com/daviddrysdale/python-phonenumbers/blob/dev/python/phonenumbers/phonenumberutil.py) + 'E164' = 0 + 'INTERNATIONAL' = 1 + 'NATIONAL' = 2 + 'RFC3966' = 3 + :type force_format: str + :rtype: str + """ + try: + phone_nbr = phone_parse(number, country_code) + except (phonenumbers.phonenumberutil.NumberParseException, UserError) as e: + if raise_exception: + raise + else: + return number + if force_format == 'E164': + phone_fmt = phonenumbers.PhoneNumberFormat.E164 + elif force_format == 'RFC3966': + phone_fmt = phonenumbers.PhoneNumberFormat.RFC3966 + elif force_format == 'INTERNATIONAL' or phone_nbr.country_code != country_phone_code: + phone_fmt = phonenumbers.PhoneNumberFormat.INTERNATIONAL + else: + phone_fmt = phonenumbers.PhoneNumberFormat.NATIONAL + return phonenumbers.format_number(phone_nbr, phone_fmt) + +except ImportError: + + def phone_parse(number, country_code): + return False + + def phone_format(number, country_code, country_phone_code, force_format='INTERNATIONAL', raise_exception=True): + global _phonenumbers_lib_warning + if not _phonenumbers_lib_warning: + _logger.info( + "The `phonenumbers` Python module is not installed, contact numbers will not be " + "verified. Please install the `phonenumbers` Python module." + ) + _phonenumbers_lib_warning = True + return number + + +def phone_sanitize_numbers(numbers, country_code, country_phone_code, force_format='E164'): + """ Given a list of numbers, return parsezd and sanitized information + + :return dict: {number: { + 'sanitized': sanitized and formated number or False (if cannot format) + 'code': 'empty' (number was a void string), 'invalid' (error) or False (sanitize ok) + 'msg': error message when 'invalid' + }} + """ + if not isinstance(numbers, (list)): + raise NotImplementedError() + result = dict.fromkeys(numbers, False) + for number in numbers: + if not number: + result[number] = {'sanitized': False, 'code': 'empty', 'msg': False} + continue + try: + stripped = number.strip() + sanitized = phone_format( + stripped, country_code, country_phone_code, + force_format=force_format, raise_exception=True) + except Exception as e: + result[number] = {'sanitized': False, 'code': 'invalid', 'msg': str(e)} + else: + result[number] = {'sanitized': sanitized, 'code': False, 'msg': False} + return result + + +def phone_sanitize_numbers_w_record(numbers, record, country=False, record_country_fname='country_id', force_format='E164'): + if not isinstance(numbers, (list)): + raise NotImplementedError() + if not country: + if record and record_country_fname and hasattr(record, record_country_fname) and record[record_country_fname]: + country = record[record_country_fname] + elif record: + country = record.env.company.country_id + country_code = country.code if country else None + country_phone_code = country.phone_code if country else None + return phone_sanitize_numbers(numbers, country_code, country_phone_code, force_format=force_format) |
