From 8b5e7e251e5a98b546cd38bab115f48da387d8d7 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 14 Aug 2026 12:14:39 -0300 Subject: [PATCH] feat: normalizar_telefone_com_ddi/normalizar_uf/normalizar_cep Co-Authored-By: Claude Sonnet 5 --- app/normalize.py | 33 +++++++++++++++++++++++++++++++++ tests/test_normalize.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/app/normalize.py b/app/normalize.py index 19943df..fff2b61 100644 --- a/app/normalize.py +++ b/app/normalize.py @@ -46,6 +46,39 @@ def normalizar_telefone(bruto: str | None) -> str: return _RE_NAO_DIGITO.sub("", bruto or "") +_RE_NAO_LETRA = re.compile(r"[^A-Z]") + + +def normalizar_telefone_com_ddi(bruto: str | None) -> str: + """ + Remove máscara (normalizar_telefone) e garante o DDI 55 embutido no + início — usado para TELEFONE/CELULAR de CLIENTE, que passam a ser + gravados sempre com DDI, mesmo que o usuário não digite (mesmo padrão + que CLIENTE_CONTATO.TELEFONE já usa para envio de WhatsApp). + + Um valor de 12-13 dígitos começando com "55" é tratado como já tendo + DDI (não duplica). Qualquer outro tamanho não vazio recebe "55" na + frente. Vazio continua vazio (campo não obrigatório). + """ + digitos = normalizar_telefone(bruto) + if not digitos: + return "" + if digitos.startswith("55") and len(digitos) in (12, 13): + return digitos + return "55" + digitos + + +def normalizar_uf(bruto: str | None) -> str: + """Só letras, maiúsculas, no máximo 2 caracteres.""" + limpo = _RE_NAO_LETRA.sub("", (bruto or "").upper()) + return limpo[:2] + + +def normalizar_cep(bruto: str | None) -> str: + """Só dígitos, no máximo 8 caracteres (sem traço).""" + return _RE_NAO_DIGITO.sub("", bruto or "")[:8] + + _PESOS_CPF_DV1 = [10, 9, 8, 7, 6, 5, 4, 3, 2] _PESOS_CPF_DV2 = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2] _PESOS_CNPJ_DV1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] diff --git a/tests/test_normalize.py b/tests/test_normalize.py index 86e8f46..b7b6c0d 100644 --- a/tests/test_normalize.py +++ b/tests/test_normalize.py @@ -78,3 +78,38 @@ def test_validar_dv_cnpj_alfanumerico_correto(): def test_validar_dv_cnpj_alfanumerico_incorreto(): assert validar_dv_cnpj("00000000E08G13") is False + + +from app.normalize import normalizar_telefone_com_ddi, normalizar_uf, normalizar_cep + + +def test_normaliza_telefone_com_ddi_prefixa_55_quando_ausente(): + assert normalizar_telefone_com_ddi("(75) 3333-4444") == "557533334444" + assert normalizar_telefone_com_ddi("(75) 99909-1780") == "5575999091780" + + +def test_normaliza_telefone_com_ddi_nao_duplica_55_ja_presente(): + assert normalizar_telefone_com_ddi("55 75 99909-1780") == "5575999091780" + assert normalizar_telefone_com_ddi("5575333344440") != "555575333344440" + + +def test_normaliza_telefone_com_ddi_vazio_continua_vazio(): + assert normalizar_telefone_com_ddi("") == "" + assert normalizar_telefone_com_ddi(None) == "" + + +def test_normaliza_uf_maiusculas_e_trunca(): + assert normalizar_uf("ba") == "BA" + assert normalizar_uf(" sp ") == "SP" + assert normalizar_uf("SAO") == "SA" + + +def test_normaliza_uf_remove_numeros_e_simbolos(): + assert normalizar_uf("B4!") == "B" + assert normalizar_uf(None) == "" + + +def test_normaliza_cep_so_digitos_e_trunca(): + assert normalizar_cep("44430-174") == "44430174" + assert normalizar_cep("44.430-174-extra") == "44430174" + assert normalizar_cep(None) == ""