2.5 KiB
2.5 KiB
Etapa 04 — Normalizador e padronização de dados
Objetivo
Implementar o módulo normalizer/ que transforma os LeadBrutoDTO extraídos na etapa 03 em dados padronizados prontos para persistência, conforme as regras definidas em ARQUITETURA-SCHEMA.md seção 5.
Contexto
Esta etapa não persiste nada ainda — produz um LeadNormalizadoDTO a partir do LeadBrutoDTO. A persistência com deduplicação é a etapa 06 (junto com a API).
Tarefas
- Criar
normalizer/NomeNormalizer:- Trim + colapsar espaços múltiplos
- Title Case, preservando em maiúsculo as siglas societárias:
LTDA,ME,EIRELI,S/A,S.A. - Remover caracteres de controle/emoji
- Criar
normalizer/TelefoneNormalizer:- Extrair apenas dígitos do texto bruto
- Assumir DDI
+55se ausente - Validar tamanho (DDD de 2 dígitos + número de 8 ou 9 dígitos); se inválido, retornar
nullno campo normalizado mas manter o bruto - Formatar em E.164 (
+5543999999999)
- Criar
normalizer/CnpjValidator:- Extrair apenas dígitos (14 posições)
- Implementar validação de dígito verificador (algoritmo módulo 11)
- Se inválido, descartar o CNPJ (gravar
null) em vez de persistir um valor incorreto
- Criar
normalizer/RamoMapper:- Buscar na tabela
ramos.aliases(JSONB) se a categoria bruta já tem mapeamento conhecido - Se encontrar, retornar o
ramo_idcorrespondente - Se não encontrar, retornar
ramo_id = nulle manter a categoria bruta emcategoria_brutapara curadoria manual posterior
- Buscar na tabela
- Criar
normalizer/DedupHashCalculator:- Calcular
hash_dedup = SHA-256(nomeNormalizado + "|" + telefoneE164)
- Calcular
- Criar
normalizer/LeadNormalizerServiceque orquestra os passos acima e produz oLeadNormalizadoDTOcompleto a partir de umLeadBrutoDTO - Escrever testes unitários para cada normalizador, cobrindo casos-limite:
- Telefone sem DDD, com formatação variada (parênteses, traços, espaços)
- CNPJ com dígito verificador inválido
- Nome com sigla societária em posições diferentes
- Categoria bruta sem mapeamento conhecido em
ramos
Critérios de aceite
- Todos os normalizadores implementados e cobertos por testes unitários com casos-limite
- CNPJ inválido nunca é persistido como válido
- Telefone sempre sai em E.164 quando válido, ou
nullquando não for possível normalizar - Ramo sem mapeamento conhecido não quebra o fluxo — apenas fica pendente de curadoria
hash_dedupcalculado de forma determinística e reproduzível para o mesmo par nome+telefone