""" Consulta de CNPJ na BrasilAPI (https://brasilapi.com.br/api/cnpj/v1) para preencher automaticamente o formulário de cliente. Fonte pública/gratuita, sem autenticação, mantida pela comunidade a partir de dados abertos da Receita Federal — não é a API oficial da Receita (que não tem consulta pública direta por CNPJ). Só faz sentido para CNPJ (empresa) — CPF é dado pessoal e não tem consulta pública, então o chamador nunca deve passar um CPF aqui (ver app/routers/clientes.py, que checa o tipo via normalizar_documento antes). Degrada de forma segura: qualquer falha (CNPJ não encontrado, rede fora do ar, formato que a BrasilAPI ainda não reconhece — o novo CNPJ alfanumérico, vigente desde 31/07/2026, pode não estar coberto por todo provedor ainda) retorna None. O formulário simplesmente não preenche nada sozinho nesse caso. """ import httpx _BASE_URL = "https://brasilapi.com.br/api/cnpj/v1" def consultar_cnpj(cnpj_normalizado: str) -> dict | None: """ cnpj_normalizado: 14 caracteres (12 alfanuméricos + 2 dígitos), já sem máscara — ver app/normalize.py. Retorna um dict só com os campos que existem em CLIENTE, prontos para preencher o formulário, ou None se não encontrou/a consulta falhou. """ if len(cnpj_normalizado) != 14: return None try: resposta = httpx.get(f"{_BASE_URL}/{cnpj_normalizado}", timeout=8.0) if resposta.status_code != 200: return None dados = resposta.json() except (httpx.HTTPError, ValueError): return None if not isinstance(dados, dict): return None logradouro = dados.get("logradouro") or "" numero = dados.get("numero") or "" endereco = f"{logradouro}, {numero}" if numero else logradouro return { "RAZAO": dados.get("razao_social") or "", "FANTASIA": dados.get("nome_fantasia") or dados.get("razao_social") or "", "ENDERECO": endereco[:45], # CLIENTE.ENDERECO é varchar(45) "CIDADE": dados.get("municipio") or "", "BAIRRO": dados.get("bairro") or "", "UF": dados.get("uf") or "", "CEP": (dados.get("cep") or "")[:10], "TELEFONE": dados.get("ddd_telefone_1") or "", "EMAIL": dados.get("email") or "", }