changeset cba01f8cd768 in modules/party:default
details: https://hg.tryton.org/modules/party?cmd=changeset;node=cba01f8cd768
description:
        Use country code as local prefix to parse phone numbers

        issue7831
        review52521002
diffstat:

 CHANGELOG                             |   2 +
 contact_mechanism.py                  |  44 +++++++++++++++++++++-------------
 tests/scenario_party_phone_number.rst |  41 ++++++++++++++++++++++++++++++++
 tests/test_party.py                   |   5 +++
 4 files changed, 75 insertions(+), 17 deletions(-)

diffs (149 lines):

diff -r 77dc19b2db36 -r cba01f8cd768 CHANGELOG
--- a/CHANGELOG Mon Oct 15 15:53:48 2018 +0200
+++ b/CHANGELOG Thu Dec 13 18:48:11 2018 +0100
@@ -1,3 +1,5 @@
+* Use country code as local prefix to parse phone numbers
+
 Version 5.0.0 - 2018-10-01
 * Bug fixes (see mercurial logs for details)
 * Support attention party in address format
diff -r 77dc19b2db36 -r cba01f8cd768 contact_mechanism.py
--- a/contact_mechanism.py      Mon Oct 15 15:53:48 2018 +0200
+++ b/contact_mechanism.py      Thu Dec 13 18:48:11 2018 +0100
@@ -1,5 +1,6 @@
 # This file is part of Tryton.  The COPYRIGHT file at the top level of
 # this repository contains the full copyright notices and license terms.
+from itertools import chain
 try:
     import phonenumbers
     from phonenumbers import PhoneNumberFormat, NumberParseException
@@ -126,26 +127,37 @@
             return 'fax:%s' % value
         return None
 
-    @classmethod
-    def format_value(cls, value=None, type_=None):
-        if phonenumbers and type_ in _PHONE_TYPES:
+    @fields.depends('party', '_parent_party.addreses')
+    def _phone_country_codes(self):
+        if self.party:
+            for address in self.party.addresses:
+                if address.country:
+                    yield address.country.code
+
+    @fields.depends(methods=['_phone_country_codes'])
+    def _parse_phonenumber(self, value):
+        for country_code in chain(self._phone_country_codes(), [None]):
             try:
-                phonenumber = phonenumbers.parse(value)
+                # Country code is ignored if value has an international prefix
+                return phonenumbers.parse(value, country_code)
             except NumberParseException:
                 pass
-            else:
+        return None
+
+    @fields.depends(methods=['_parse_phonenumber'])
+    def format_value(self, value=None, type_=None):
+        if phonenumbers and type_ in _PHONE_TYPES:
+            phonenumber = self._parse_phonenumber(value)
+            if phonenumber:
                 value = phonenumbers.format_number(
                     phonenumber, PhoneNumberFormat.INTERNATIONAL)
         return value
 
-    @classmethod
-    def format_value_compact(cls, value=None, type_=None):
+    @fields.depends(methods=['_parse_phonenumber'])
+    def format_value_compact(self, value=None, type_=None):
         if phonenumbers and type_ in _PHONE_TYPES:
-            try:
-                phonenumber = phonenumbers.parse(value)
-            except NumberParseException:
-                pass
-            else:
+            phonenumber = self._parse_phonenumber(value)
+            if phonenumber:
                 value = phonenumbers.format_number(
                     phonenumber, PhoneNumberFormat.E164)
         return value
@@ -155,7 +167,8 @@
         #  Setting value is done by on_changes
         pass
 
-    @fields.depends(methods=['on_change_with_url'])
+    @fields.depends(
+        methods=['on_change_with_url', 'format_value', 'format_value_compact'])
     def _change_value(self, value, type_):
         self.value = self.format_value(value=value, type_=type_)
         self.value_compact = self.format_value_compact(
@@ -240,10 +253,7 @@
     def check_valid_phonenumber(self):
         if not phonenumbers or self.type not in _PHONE_TYPES:
             return
-        try:
-            phonenumber = phonenumbers.parse(self.value)
-        except NumberParseException:
-            phonenumber = None
+        phonenumber = self._parse_phonenumber(self.value)
         if not (phonenumber and phonenumbers.is_valid_number(phonenumber)):
             self.raise_user_error(
                 'invalid_phonenumber', {
diff -r 77dc19b2db36 -r cba01f8cd768 tests/scenario_party_phone_number.rst
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_party_phone_number.rst     Thu Dec 13 18:48:11 2018 +0100
@@ -0,0 +1,41 @@
+===========================
+Party Phone Number Scenario
+===========================
+
+Imports::
+
+    >>> from proteus import Model, Wizard
+    >>> from trytond.tests.tools import activate_modules
+
+Install party::
+
+    >>> config = activate_modules('party')
+
+Create a country::
+
+    >>> Country = Model.get('country.country')
+    >>> spain = Country(name='Spain', code='ES')
+    >>> spain.save()
+
+Create a party related to the country::
+
+    >>> Party = Model.get('party.party')
+    >>> party = Party(name='Pam')
+    >>> address, = party.addresses
+    >>> address.country = spain
+
+The country phone prefix is set when creating a phone of this party::
+
+    >>> local_phone = party.contact_mechanisms.new()
+    >>> local_phone.type = 'phone'
+    >>> local_phone.value = '666666666'
+    >>> local_phone.value
+    '+34 666 66 66 66'
+
+The phone prefix is respected when using international prefix::
+
+    >>> international_phone = party.contact_mechanisms.new()
+    >>> international_phone.type = 'phone'
+    >>> international_phone.value = '+442083661178'
+    >>> international_phone.value
+    '+44 20 8366 1178'
diff -r 77dc19b2db36 -r cba01f8cd768 tests/test_party.py
--- a/tests/test_party.py       Mon Oct 15 15:53:48 2018 +0200
+++ b/tests/test_party.py       Thu Dec 13 18:48:11 2018 +0100
@@ -428,4 +428,9 @@
             tearDown=doctest_teardown, encoding='utf-8',
             checker=doctest_checker,
             optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+    suite.addTests(doctest.DocFileSuite(
+            'scenario_party_phone_number.rst',
+            tearDown=doctest_teardown, encoding='utf-8',
+            checker=doctest_checker,
+            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
     return suite

Reply via email to