brdoc icon indicating copy to clipboard operation
brdoc copied to clipboard

Implements phone validator

Open tiagompalte opened this issue 1 year ago • 2 comments

Implementação de validação de número de celular e de telefone, retornando o UF referente ao DDD do número.

https://github.com/paemuri/brdoc/issues/21

tiagompalte avatar Jan 03 '24 00:01 tiagompalte

Opa, tudo bem @tiagompalte?

Eu estava dando uma olhada no seu código, você chegou a seguir alguma referência para a validação dos números de telefone? Outra dúvida, o seu código deveria validar também telefones residenciais?

Eu precisei fazer algo do tipo recentemente e segui esta referencia, que contém os padões para os números de telefone: https://www.teleco.com.br/num.asp

DIto isso, eu adicionei alguns testes e fiz algumas modificações no seu código a fim de seguir esse padrão.

Irei deixar essas modificações nesse comentário, a fim de que você avalie e veja se faz sentido implementá-las no seu PR :grin:

  • phone_test.go
func TestIsPhone(t *testing.T) {
	for i, tc := range []struct {
		name          string
		expectedValid bool
		expectedUf    FederativeUnit
		v             string
	}{
		{"Valid_ShouldReturnTrueUfSP", true, SP, "+55(11)999999999"},
		{"Valid_ShouldReturnTrueUfSP", true, SP, "55(11)999999999"},
		{"Valid_ShouldReturnTrueUfPR", true, PR, "(41)999999999"},
		{"Valid_ShouldReturnTrueUfDF", true, DF, "(61)32222222"},
		{"Valid_ShouldReturnTrueUfAC", true, AC, "(68) 99988-1234"},
		{"Valid_ShouldReturnTrueUfPE", true, PE, "8198988888"},
		{"Valid_ShouldReturnTrueUfPE", true, PE, "558198988888"},
		{"Valid_ShouldReturnFalseUfAC", true, SP, "12 9999-9999"},
		{"InvalidDDI_ShouldReturnFalseUfAC", false, AC, "+01(11)999999999"},
		{"InvalidDDD_ShouldReturnFalseUfAC_1", false, AC, "(01)999999999"},
		{"InvalidDDD_ShouldReturnFalseUfAC_2", false, AC, "55(01)999999999"},
		{"InvalidPattern_ShouldReturnFalseUfAC_1", true, SP, "11 9999 9999"},
		{"InvalidPattern_ShouldReturnFalseUfAC_2", true, SP, "11 9 9999 9999"},
		{"InvalidPattern_ShouldReturnFalseUfAC_3", false, AC, "11.99999.9999"},
		{"InvalidPattern_ShouldReturnFalseUfAC_4", false, AC, "11 99999/9999"},
		{"InvalidPattern_ShouldReturnFalseUfAC_5", false, AC, "(11)9999999-99"},
		{"Teste_novo_1", true, SP, "+55 (11) 3340-2800"},
		{"Teste_novo_2", true, SP, "+55 (12) 3340 2801"},
		{"Teste_novo_3", true, SP, "+55 (13) 33402802"},
		{"Teste_novo_4", true, SP, "+55 (14)3340-2803"},
		{"Teste_novo_5", true, SP, "+55 (15)33402804"},
		{"Teste_novo_6", true, SP, "+55 (16)3340 2805"},
		{"Teste_novo_7", true, SP, "+55 (17) 9 6340-2806"},
		{"Teste_novo_8", true, SP, "+55 (18) 9 6340 2807"},
		{"Teste_novo_9", true, SP, "+55 (19) 9 63402808"},
		{"Teste_novo_10", true, RJ, "+55 (21)9 7340-2809"},
		{"Teste_novo_11", true, RJ, "+55 (22)9 73402810"},
		{"Teste_novo_12", true, RJ, "+55 (24)9 7340 2811"},
		{"Teste_novo_13", true, ES, "+55 (27) 98340-2812"},
		{"Teste_novo_14", true, ES, "+55 (28) 98340 2813"},
		{"Teste_novo_15", true, MG, "+55 (31) 983402814"},
		{"Teste_novo_16", true, MG, "+55 (32)99340-2815"},
		{"Teste_novo_17", true, MG, "+55 (33)993402816"},
		{"Teste_novo_18", true, MG, "+55 (34)99340 2817"},
		{"Teste_novo_19", true, MG, "+55 35 3340-2818"},
		{"Teste_novo_20", true, MG, "+55 37 33402819"},
		{"Teste_novo_21", true, MG, "+55 38 3340 2820"},
		{"Teste_novo_22", true, PR, "+55 41 9 6340-2821"},
		{"Teste_novo_23", true, PR, "+55 42 9 63402822"},
		{"Teste_novo_24", true, PR, "+55 43 9 6340 2823"},
		{"Teste_novo_25", true, PR, "+55 44 97340-2824"},
		{"Teste_novo_26", true, PR, "+55 45 973402825"},
		{"Teste_novo_27", true, PR, "+55 46 97340 2826"},
	} {
		t.Run(testName(i, tc.name), func(t *testing.T) {
			t.Helper()
			isValid, uf := IsPhone(tc.v)
			assertEqual(t, tc.expectedValid, isValid)
			assertEqual(t, tc.expectedUf, uf)
		})
	}
  • phone.go
// Reference to get the correct number: https://www.teleco.com.br/num.asp
var cellPhoneRegexp = regexp.MustCompile(`^(?:(?:\+|00)?(55)\s?)?(?:\(?([1-9][0-9])\)?\s?)(?:((?:9\s?\d|[6789]{1})\d{3})(?:(\-|\s|\.))?(\d{4}))$`)
var residencialPhoneRegexp = regexp.MustCompile(`^(?:(?:\+|00)?(55)\s?)?(?:\(?([1-9][0-9])\)?\s?)(?:((?:\s?\d|[2345]{1})\d{3})(?:(\-|\s|\.))?(\d{4}))$`)

var mapDDD = map[string]FederativeUnit{
	"61": DF,
	"62": GO,
	"64": GO,
	"65": MT,
	"66": MT,
	"67": MS,
	"82": AL,
	"71": BA,
	"73": BA,
	"74": BA,
	"75": BA,
	"77": BA,
	"85": CE,
	"88": CE,
	"98": MA,
	"99": MA,
	"83": PB,
	"81": PE,
	"87": PE,
	"86": PI,
	"89": PI,
	"84": RN,
	"79": SE,
	"68": AC,
	"96": AP,
	"92": AM,
	"97": AM,
	"91": PA,
	"93": PA,
	"94": PA,
	"69": RO,
	"95": RR,
	"63": TO,
	"27": ES,
	"28": ES,
	"31": MG,
	"32": MG,
	"33": MG,
	"34": MG,
	"35": MG,
	"37": MG,
	"38": MG,
	"21": RJ,
	"22": RJ,
	"24": RJ,
	"11": SP,
	"12": SP,
	"13": SP,
	"14": SP,
	"15": SP,
	"16": SP,
	"17": SP,
	"18": SP,
	"19": SP,
	"41": PR,
	"42": PR,
	"43": PR,
	"44": PR,
	"45": PR,
	"46": PR,
	"51": RS,
	"53": RS,
	"54": RS,
	"55": RS,
	"47": SC,
	"48": SC,
	"49": SC,
}

// IsPhone verifies if `phone` is a phone or residential valid number and return UF from DDD.
func IsPhone(phone string) (isValid bool, uf FederativeUnit) {
	if !cellPhoneRegexp.MatchString(phone) && !residencialPhoneRegexp.MatchString(phone) {
		isValid = false
		return
	}

	cellPhoneGroups := cellPhoneRegexp.FindStringSubmatch(phone)
	residencialPhoneGroups := residencialPhoneRegexp.FindStringSubmatch(phone)
	var groups []string

	if cellPhoneGroups == nil {
		groups = residencialPhoneGroups
	} else {
		groups = cellPhoneGroups
	}

	groupDDD := 2
	uf, isValid = mapDDD[groups[groupDDD]]

	return
}

ArtusC avatar Feb 05 '24 11:02 ArtusC

Obrigado pela contribuição @ArtusC Código mergeado

tiagompalte avatar Feb 09 '24 23:02 tiagompalte