diff --git a/docs/authors.rst b/docs/authors.rst index 6177720b0..f11f08269 100644 --- a/docs/authors.rst +++ b/docs/authors.rst @@ -122,3 +122,4 @@ Authors * Vishal Pandey * Vladimir Nani * Abhineet Tamrakar +* Leonardo Paz Estevam \ No newline at end of file diff --git a/docs/changelog.rst b/docs/changelog.rst index f18bc43d6..62f702c11 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,6 +20,8 @@ New fields for existing flavors: (`gh-457 `_). - Added the Canadian Models fields. (`gh-465 `_). +- Added Cellphone and Landline fields in Brazilian flavor. + (`gh-471 `_) Modifications to existing flavors: diff --git a/localflavor/br/forms.py b/localflavor/br/forms.py index 4fb6f4d23..bf52044ab 100644 --- a/localflavor/br/forms.py +++ b/localflavor/br/forms.py @@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _ from .br_states import STATE_CHOICES -from .validators import BRCNPJValidator, BRCPFValidator, BRPostalCodeValidator +from .validators import BRCNPJValidator, BRCPFValidator, BRLandLineValidator, BRPostalCodeValidator, BRCellPhoneValidator process_digits_re = re.compile( r'^(\d{7})-?(\d{2})\.?(\d{4})\.?(\d)\.?(\d{2})\.?(\d{4})$' @@ -156,4 +156,35 @@ def clean(self, value): if str(mod_97_base10(value_without_digits)).zfill(2) != orig_dv: raise ValidationError(self.error_messages['invalid'], code='invalid') - return orig_value + return orig_value + +class BRCellPhoneField(CharField): + """ + A form field that validates a Cell Phone number. + + More information: + https://www.gov.br/anatel/pt-br/regulado/numeracao/tabela-servico-movel-celular + """ + + default_error_messages = { + 'invalid': _("Invalid Cell Phone, number needs to be in the format (XX)XXXXX-XXXX."), + } + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.validators.append(BRCellPhoneValidator()) + +class BRLandLineField(CharField): + """ + A form field that validates a Landline number. + + More information: + https://www.gov.br/anatel/pt-br/regulado/numeracao/tabela-servico-telefonico-fixo-comutado + """ + default_error_messages = { + 'invalid': _("Invalid Landline, number needs to be in the format (XX)XXXX-XXXX."), + } + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.validators.append(BRLandLineValidator()) diff --git a/localflavor/br/models.py b/localflavor/br/models.py index 1d06d2194..58a645a07 100644 --- a/localflavor/br/models.py +++ b/localflavor/br/models.py @@ -69,3 +69,27 @@ def __init__(self, *args, **kwargs): kwargs['max_length'] = 9 super().__init__(*args, **kwargs) self.validators.append(validators.BRPostalCodeValidator()) + +class BRLandLineField(CharField): + """ + A model field for brazilian LandLine number + + """ + description = _("Landline Number") + + def __init__(self, *args, **kwargs): + kwargs['max_length'] = 14 + super().__init__(*args, **kwargs) + self.validators.append(validators.BRLandLineValidator()) + +class BRCellPhoneField(CharField): + """ + A model field for brazilian Cell Phone number + + """ + description = _("Cell Phone Number") + + def __init__(self, *args, **kwargs): + kwargs['max_length'] = 15 + super().__init__(*args, **kwargs) + self.validators.append(validators.BRCellPhoneValidator()) diff --git a/localflavor/br/validators.py b/localflavor/br/validators.py index fee51ab54..fd0712ef6 100644 --- a/localflavor/br/validators.py +++ b/localflavor/br/validators.py @@ -7,6 +7,8 @@ postal_code_re = re.compile(r'^\d{5}-\d{3}$') cnpj_digits_re = re.compile(r'^(\d{2})[.-]?(\d{3})[.-]?(\d{3})/(\d{4})-(\d{2})$') cpf_digits_re = re.compile(r'^(\d{3})\.(\d{3})\.(\d{3})-(\d{2})$') +landline_number_re = re.compile(r'^[(][1-9][1-9][)][2-5]\d{3}-\d{4}$') +cell_phone_number_re = re.compile(r'^[(][1-9][1-9][)]9\d{4}-\d{4}$') def dv_maker(v): @@ -103,4 +105,27 @@ def __call__(self, value): if value[-2:] != orig_dv: raise ValidationError(self.message, code='invalid') if value.count(value[0]) == 11: - raise ValidationError(self.message, code='invalid') + raise ValidationError(self.message, code='invalid') + + +class BRLandLineValidator(RegexValidator): + """ + Validator for brazilian LandLine number. + + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, + regex = landline_number_re, + message = _("Invalid Landline, number needs to be in the format (XX)XXXX-XXXX."), + **kwargs) + +class BRCellPhoneValidator(RegexValidator): + """ + Validator for brazilian Cell Phone number. + + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, + regex = cell_phone_number_re, + message = _("Invalid Cell Phone, number needs to be in the format (XX)XXXXX-XXXX."), + **kwargs) diff --git a/tests/test_br/test_br.py b/tests/test_br/test_br.py index a1a3726ab..dc354173c 100644 --- a/tests/test_br/test_br.py +++ b/tests/test_br/test_br.py @@ -1,8 +1,8 @@ from django.test import SimpleTestCase from localflavor.br import models -from localflavor.br.forms import (BRCNPJField, BRCPFField, BRProcessoField, BRStateChoiceField, BRStateSelect, - BRZipCodeField) +from localflavor.br.forms import (BRCNPJField, BRCPFField, BRLandLineField, BRProcessoField, BRStateChoiceField, BRStateSelect, + BRZipCodeField, BRCellPhoneField) from tests.test_br.forms import BRPersonProfileForm @@ -222,7 +222,36 @@ def test_model_form_valid(self): for case in data_to_test: form = BRPersonProfileForm(case) - self.assertTrue(form.is_valid()) + self.assertTrue(form.is_valid()) + + def test_CellPhoneField(self): + error_format = ["Invalid Cell Phone, number needs to be in the format (XX)XXXXX-XXXX."] + valid = { + '(11)99919-2696': '(11)99919-2696', + } + invalid = { + '(08)99919-2696': error_format, + '(11)89919-2696': error_format, + '(ab)cdefg-hijk': error_format, + '(11)99919 2696': error_format, + '(11) 99919-2696': error_format, + } + self.assertFieldOutput(BRCellPhoneField, valid, invalid) + + def test_LandLineField(self): + error_format = ['Invalid Landline, number needs to be in the format (XX)XXXX-XXXX.'] + valid = { + '(11)3223-3946': '(11)3223-3946', + } + invalid = { + '(08)99919-2696': error_format, + '(11)6919-2696': error_format, + '(ab)cdefg-hijk': error_format, + '(11)3919 2696': error_format, + '(11) 3919-2696': error_format, + } + self.assertFieldOutput(BRLandLineField, valid, invalid) + class BRLocalFlavorModelTests(SimpleTestCase):