fix: corrige achados da revisao final (DDI idempotente, mascara DDI 12/13 digitos, status DV, validacao no load, autofill dispara mascaras)

Endereca 5 achados da revisao final de branch:
- Important #1: normalizar_telefone_com_ddi agora e idempotente (nao duplica 55 independente do tamanho)
- Important #2: mascara de telefone detecta DDI colado por tamanho total (12/13 digitos), nao mais so pelo campo especifico
- Minor #3: buscarCnpj pula lookup na Receita quando DV do CNPJ e invalido, preservando a mensagem de erro
- Minor #4: detectarEValidarDocumento roda uma vez no carregamento da pagina
- Minor #5: autofill da Receita dispara evento input para acionar as mascaras de UF/CEP/TELEFONE

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-14 12:31:20 -03:00
co-authored by Claude Sonnet 5
parent eec7ce21b5
commit dea9dc4401
3 changed files with 22 additions and 7 deletions
+6 -4
View File
@@ -56,14 +56,16 @@ def normalizar_telefone_com_ddi(bruto: str | None) -> str:
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).
Um valor que já começa com "55" é tratado como já tendo DDI (não
duplica), independente do tamanho — garante idempotência mesmo em
round-trips (ex.: reenvio do formulário já normalizado). Qualquer
outro valor 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):
if digitos.startswith("55"):
return digitos
return "55" + digitos
+7 -3
View File
@@ -125,13 +125,15 @@
}
$cnpj.addEventListener('input', detectarEValidarDocumento);
detectarEValidarDocumento();
function aplicarMascaraTelefone(elemento, digitosAposDdd) {
elemento.addEventListener('input', function () {
var digitos = elemento.value.replace(/\D/g, '');
// Se veio com DDI 55 colado (12-13 dígitos totais), usa só o resto.
var totalComDdi = 2 + digitosAposDdd; // DDI(2) + DDD(2) já contado em digitosAposDdd
if (digitos.length >= totalComDdi && digitos.slice(0, 2) === '55') {
// DDI 55 colado: detecta por tamanho total (12 ou 13 dígitos), não
// pelo tamanho esperado do campo específico — um número de 12
// dígitos colado no campo de celular ainda deve ter o 55 removido.
if ((digitos.length === 12 || digitos.length === 13) && digitos.slice(0, 2) === '55') {
digitos = digitos.slice(2);
}
digitos = digitos.slice(0, digitosAposDdd);
@@ -181,6 +183,7 @@
async function buscarCnpj() {
var limpo = normalizarCnpj($cnpj.value);
if (limpo.length !== 14) return;
if (limpo.length === 14 && !validarDvCnpj(limpo)) return;
if ($status) $status.textContent = 'Buscando dados do CNPJ...';
@@ -196,6 +199,7 @@
var $input = document.getElementById(campo);
if ($input && !$input.value && corpo.dados[campo]) {
$input.value = corpo.dados[campo];
$input.dispatchEvent(new Event('input'));
preencheu = true;
}
});
+9
View File
@@ -98,6 +98,15 @@ def test_normaliza_telefone_com_ddi_vazio_continua_vazio():
assert normalizar_telefone_com_ddi(None) == ""
def test_normaliza_telefone_com_ddi_e_idempotente():
"""Aplicar a função duas vezes seguidas nunca deve dobrar o DDI."""
casos = ["(75) 3333-4444", "(75) 99909-1780", "5575999091780", "3333-4444", ""]
for bruto in casos:
uma_vez = normalizar_telefone_com_ddi(bruto)
duas_vezes = normalizar_telefone_com_ddi(uma_vez)
assert duas_vezes == uma_vez, f"não é idempotente para {bruto!r}: {uma_vez!r} -> {duas_vezes!r}"
def test_normaliza_uf_maiusculas_e_trunca():
assert normalizar_uf("ba") == "BA"
assert normalizar_uf(" sp ") == "SP"