# Sothis Contratação API ## Visão Geral A **Sothis Contratação API** é uma solução robusta para automatizar e facilitar o processo de novas contratações. A aplicação gerencia consultas de viabilidade técnica e a criação de prospectos de clientes no sistema integrado Hubsoft. ### Funcionalidades Principais 1. **Consulta de Viabilidade por CEP e Número**: Verifica a viabilidade técnica de um endereço e retorna informações sobre disponibilidade de serviços (dedicado e não-dedicado) com base na proximidade de pontos de presença. 2. **Consulta de Viabilidade por Coordenadas**: Consulta viabilidade usando latitude e longitude com reverse geocoding. 3. **Criação de Prospectos**: Registra novos clientes (Pessoa Física ou Jurídica) no sistema de gestão Hubsoft com suporte a diferentes planos de banda larga. ## Features Técnicas - **Express.js 5.1**: Framework web moderno para construção de APIs RESTful. - **Arquitetura Modular**: Estrutura baseada em MVC com separação clara entre Controller, Service, Repository e Model. - **Integração com Múltiplas APIs**: - **Google Maps Geocoding**: Para geocodificação e reverse geocoding de endereços. - **GeoGrid API**: Consulta de pontos de presença e viabilidade técnica. - **Hubsoft API**: Gestão de prospectos e clientes. - **CEP Validation**: Integração com `cep-promise` para validação e busca de endereços brasileiros. - **Logging Avançado**: Sistema de logging estruturado com `winston` e arquivo rotativo diário. - **Configuração por Ambiente**: Suporte a múltiplos ambientes (desenvolvimento/produção) via `dotenv`. - **CORS Configurado**: Habilitado para domínios específicos (`sothis.com.br` e `bandalarga.srv.br`). - **PostgreSQL Ready**: Preparado para persistência de dados com `pg`. - **Desenvolvimento Otimizado**: Hot-reload automático com `nodemon`. ## Pré-requisitos - Node.js (versão 18.x ou superior recomendada) - npm (geralmente instalado junto com o Node.js) - PostgreSQL (opcional, para persistência de dados) - Chaves de API: Google Maps, GeoGrid, Hubsoft ## 1. Instalação Clone o repositório e instale as dependências: ```bash npm install ``` ## 2. Configuração A aplicação utiliza arquivos `.env` para carregar suas configurações. Você precisará criar dois arquivos na raiz do projeto: - `.env.development` (para ambiente de desenvolvimento) - `.env.production` (para ambiente de produção) ### Variáveis de Ambiente Obrigatórias ```env # Servidor PORT=3000 NODE_ENV=development # Google Maps Geocoding API (para geocodificação e reverse geocoding) GOOGLE_API_KEY=sua_chave_google_maps_aqui # GeoGrid API (para consulta de viabilidade técnica) GEOGRID_API_URL=https://.../viabilidade/raio # URL COMPLETA da consulta por raio GEOGRID_API_KEY=sua_chave_geogrid_aqui GEOGRID_API_COOKIE=seu_cookie_geogrid_aqui # Distância REAL de trajeto (opcionais — têm defaults seguros) GEOGRID_API_BASE_URL=https://.../vale/api/v3 # base p/ o endpoint de trajeto; se ausente, derivada da URL de consulta GEOGRID_TRAJETO_MODO=walking # modo do trajeto GEOGRID_TRAJETO_TOP_N=3 # nº de caixas roteadas na consulta individual (precisão) GEOGRID_TRAJETO_TOP_N_LOTE=2 # nº de caixas roteadas por item no lote (a planilha mostra 2 caixas) GEOGRID_CONCURRENCY=5 # chamadas externas simultâneas no lote # Hubsoft API (para gestão de prospectos) HUBSOFT_URL=https://seu-dominio.hubsoft.com.br HUBSOFT_CLIENT_ID=seu_client_id_hubsoft HUBSOFT_CLIENT_SECRET=seu_client_secret_hubsoft HUBSOFT_USERNAME=seu_usuario_hubsoft HUBSOFT_PASSWORD=sua_senha_hubsoft HUBSOFT_GRANT_TYPE=password # Database PostgreSQL (opcional, para persistência de viabilidades) DB_HOST=localhost DB_PORT=5432 DB_USER=seu_usuario_postgres DB_PASSWORD=sua_senha_postgres DB_NAME=contratacao_db ``` ### Classificação de Pastas (provedor) O provedor é resolvido pelo **prefixo da sigla da pasta** no GeoGrid (não há configuração no `.env`): - `s-...` → **Sothis** (rede própria). - `p-...` → **parceiro**; o provedor é o nome que vem depois do `-` (ex.: `p-Vivo` → `Vivo`). - Um segmento `sub` após o `-` marca rede **subterrânea** e prefixa `(Subterrâneo)` no provedor (ex.: `s-sub-Barueri` → `(Subterrâneo) Sothis`). - Qualquer sigla fora dessa convenção é considerada **não elegível** (ignorada). ## 3. Rodando a Aplicação ### Modo de Desenvolvimento Este comando inicia a API com `nodemon`, que reinicia o servidor automaticamente a cada alteração nos arquivos. As configurações serão carregadas do `.env.development`. ```bash npm run dev:api ``` A API será iniciada na porta configurada (padrão `3000`) e exibirá: ``` 🚀 Servidor API rodando na porta 3000 em modo development ``` ### Modo de Produção Este comando inicia a API de forma otimizada para produção usando `node`. As configurações serão carregadas do `.env.production`. ```bash npm run start:api ``` --- ## Logging e Monitoramento A aplicação utiliza **Winston** para logging estruturado com as seguintes características: - **Arquivos de Log**: Criados automaticamente no diretório `logs/` - **Rotação Diária**: Novos arquivos criados a cada dia com formato `application-YYYY-MM-DD.log` - **Níveis de Log**: - `info`: Requisições recebidas, operações bem-sucedidas - `warn`: Advertências e situações inesperadas - `error`: Erros e exceções ### Exemplo de Logs ``` 2026-05-20T10:30:45.123Z [info]: 🚀 Servidor API rodando na porta 3000 em modo development 2026-05-20T10:31:20.456Z [info]: Requisição recebida: POST /api/viabilidade - IP: 127.0.0.1 2026-05-20T10:31:21.789Z [info]: Endereço obtido com sucesso via cep-promise 2026-05-20T10:31:23.234Z [info]: Coordenadas obtidas com sucesso - lat: -23.5070, lon: -46.4036 2026-05-20T10:31:25.567Z [info]: Viabilidade salva com sucesso ``` --- ## Tratamento de Erros A API implementa tratamento robusto de erros: 1. **Validação de Entrada**: CEP e número são obrigatórios na consulta de viabilidade 2. **Erros de Integração**: Erros de terceiros são tratados e retornam respostas HTTP apropriadas 3. **Logging de Erros**: Todos os erros são registrados com stack trace completo 4. **Respostas Consistentes**: Erros retornam status HTTP apropriado e mensagem descritiva --- ## Integração com Serviços Externos ### Google Maps Geocoding - **Uso**: Converter endereço em coordenadas e vice-versa (reverse geocoding) - **Rate Limit**: Respeitar limites da Google API ### GeoGrid API - **Uso**: Consultar pontos de presença e viabilidade de instalação - **Autenticação**: Via API Key e Cookie ### Hubsoft API - **Uso**: Criação e gestão de prospectos - **Autenticação**: OAuth 2.0 com grant_type=password --- ## Configuração de CORS A API está configurada para aceitar requisições apenas de domínios específicos: ``` ✅ https://sothis.com.br ✅ https://bandalarga.srv.br ``` **Métodos HTTP Permitidos**: - GET, POST, PUT, DELETE, OPTIONS **Headers Permitidos**: - Content-Type - Authorization Para adicionar novos domínios, edite o arquivo [app.js:18](src/app.js#L18). --- ## Documentação da API O prefixo para todos os endpoints é `/api`. ### 1. Consulta de Viabilidade por CEP Verifica a viabilidade técnica de um endereço usando CEP e número. - **Endpoint**: `POST /viabilidade` - **Descrição**: Realiza geocodificação do endereço e consulta viabilidade na GeoGrid baseado em pontos de presença. - **Corpo da Requisição** (`application/json`): ```json { "nome": "João Silva", "email": "joao@email.com", "telefone": "11987654321", "cep": "06419240", "numero": "303", "source": "" } ``` - **Resposta de Sucesso** (`200 OK`): ```json { "nome": "João Silva", "email": "joao@email.com", "telefone": "11987654321", "logradouro": "Rua Imirim", "numero": "303", "bairro": "Chácaras Marco", "cidade": "Barueri", "estado": "SP", "cep": "06419240", "naoDedicado": true, "dedicado": true, "distancia": 250, "provedor": "Sothis" } ``` **Campos da Resposta**: - `naoDedicado`: Serviço disponível em banda compartilhada (distância real ≤ 500m) - `dedicado`: Serviço disponível em banda dedicada (distância real ≤ 1000m) - `distancia`: Distância **real de trajeto** em metros até a caixa mais próxima (ou "5KM+" se não houver caixa no raio). Se o trajeto falhar, cai para a distância em linha reta. - `distanciaReta`: Distância em **linha reta** em metros (aditivo, para comparação). - `provedor`: Identificação do provedor pela convenção de prefixo da sigla de pasta (ver "Classificação de Pastas") > **Nota:** a regra de viabilidade e o campo `distancia` passaram a usar a **distância real de trajeto** (via GeoGrid `/integracao/trajeto/cordenada`). Como a real é sempre ≥ a linha reta, endereços de borda podem deixar de viabilizar em relação ao comportamento anterior. - **Respostas de Erro**: - `400 Bad Request`: Se `cep` ou `numero` não forem fornecidos. - `422 Unprocessable Entity`: Se os dados de endereço estiverem incompletos ou inválidos. - `502 Bad Gateway`: Se o CEP for inválido ou não encontrado na biblioteca `cep-promise`. - `500 Internal Server Error`: Para outros erros no processo. --- ### 1.1. Consulta de Viabilidade em Lote Consulta viabilidade para vários endereços/coordenadas de uma vez (usado pelo viabiliza). Reusa o mesmo core de viabilidade, com top-N de trajeto reduzido e concorrência limitada. - **Endpoint**: `POST /viabilidade/lote` - **Corpo da Requisição** (`application/json`): ```json { "itens": [ { "cep": "06419240", "numero": "303" }, { "latitude": "-23.5070", "longitude": "-46.4036" } ], "modo": "walking" } ``` - **Resposta de Sucesso** (`200 OK`): array alinhado por índice ao `itens` enviado. ```json { "resultados": [ { "index": 0, "provedor": "Sothis", "distancia": 630, "distanciaReta": 300, "distanciaReal": 630, "dedicado": true, "naoDedicado": false, "caixas": [ { "provedor": "Sothis", "sigla": "A", "distancia": 420, "distanciaReta": 300, "distanciaReal": 420, "dedicado": true, "naoDedicado": true }, { "provedor": "Parceiro - X", "sigla": "B", "distancia": 900, "distanciaReta": 700, "distanciaReal": 900, "dedicado": true, "naoDedicado": false } ] }, { "index": 1, "erro": "Item inválido: informe cep+numero ou latitude+longitude." } ] } ``` - `caixas`: detalhe por caixa (as mais próximas em linha reta primeiro), cada uma com **seu próprio provedor**, distância de trajeto e classificação. No lote a seleção é **mista** (as N mais próximas de *qualquer* provedor — rede própria e parceiros), então caixas na mesma linha podem ter provedores diferentes. O viabiliza usa as **2 primeiras** para montar as colunas da planilha (Provedor/Não Dedicado/Dedicado/Distância por caixa). A consulta individual (`/viabilidade`) continua priorizando Sothis. - Cada item é resolvido de forma independente: um erro em um item não derruba os demais (vem no campo `erro`). - Coordenadas/CEPs repetidos são deduplicados (uma chamada externa por chave única). --- ### 2. Consulta de Viabilidade por Coordenadas Verifica a viabilidade técnica usando latitude e longitude com reverse geocoding. - **Endpoint**: `POST /viabilidade/lat-long` - **Descrição**: Consulta viabilidade baseado em coordenadas geográficas e realiza reverse geocoding. - **Corpo da Requisição** (`application/json`): ```json { "latitude": "-23.5070", "longitude": "-46.4036" } ``` - **Resposta de Sucesso** (`200 OK`): ```json { "endereco": "Avenida Paulista, 1000 - Bela Vista - São Paulo, SP", "naoDedicado": false, "dedicado": true, "distancia": 750, "provedor": "Sothis" } ``` - **Respostas de Erro**: - `500 Internal Server Error`: Se ocorrer erro na consulta ou reverse geocoding. --- ### 3. Criação de Prospecto Cria um novo cliente (Pessoa Física ou Jurídica) no Hubsoft. - **Endpoint**: `POST /prospecto` - **Descrição**: Registra um novo prospecto no sistema Hubsoft com dados de contato e plano selecionado. - **Corpo da Requisição** (`application/json`): **Para Pessoa Física (CPF não vazio)**: ```json { "prospectData": { "Nome completo": "João Silva Santos", "CPF": "123.456.789-00", "Nome da mãe": "Maria Silva", "Data de nascimento": "15/05/1985", "E-mail": "joao@email.com", "Celular": "(11) 98765-4321", "CEP": "06419240", "Logradouro": "Rua Imirim", "Número": "303", "Complemento": "Apto 42", "Bairro": "Chácaras Marco", "Descrição": "100 Mega + Super WiFi", "Valor (mensal)": "R$ 119,90" } } ``` **Para Pessoa Jurídica (CPF vazio, CNPJ preenchido)**: ```json { "prospectData": { "Razão Social": "Empresa LTDA", "CNPJ": "12.345.678/0001-90", "E-mail": "contato@empresa.com", "Celular": "(11) 98765-4321", "CEP": "06419240", "Logradouro": "Rua Imirim", "Número": "303", "Complemento": "", "Bairro": "Chácaras Marco", "Descrição": "500 Mega + Super WiFi + IP Fixo", "Valor (mensal)": "R$ 249,90", "CPF:": "" } } ``` **Planos Disponíveis**: - `100 Mega + Super WiFi` (ID: 22) - `200 Mega + Super WiFi` (ID: 94) - `500 Mega + Super WiFi` (ID: 96) - `700 Mega + Super WiFi` (ID: 97) - `1 Gb + Super WiFi` (ID: 32) - Variações com `+ IP Fixo` - **Resposta de Sucesso** (`200 OK`): ```json { "message": "Prospecto criado com sucesso", "data": { "tipo_pessoa": "pf", "nome_razao_social": "João Silva Santos", "cpf_cnpj": "123.456.789-00", "email": "joao@email.com", "telefone": "11987654321", "endereco": "Rua Imirim", "numero": "303", "bairro": "Chácaras Marco", "cep": "06419240", "servico": { "id_servico": 22, "valor": 119.90 } } } ``` - **Respostas de Erro**: - `400 Bad Request`: Se o plano informado for inválido ou não encontrado. - `500 Internal Server Error`: Se ocorrer erro na comunicação com Hubsoft. --- ## Estrutura do Projeto ``` src/ ├── app.js # Ponto de entrada da aplicação ├── routes/ │ └── routes.js # Definição de rotas ├── modules/ │ └── contratacao/ │ ├── contratacao.controller.js # Controladoras HTTP │ ├── contratacao.service.js # Lógica de negócio │ ├── contratacao.repository.js # Acesso a dados │ └── contratacao.model.js # Modelos de dados └── shared/ ├── apis/ │ ├── googleService.js # Integração Google Maps │ ├── geogridService.js # Integração GeoGrid │ └── hubsoftService.js # Integração Hubsoft ├── config/ │ ├── environment.js # Carregamento de variáveis │ ├── apiConfig.js # Configurações de API │ └── dbConfig.js # Configurações de banco └── utils/ └── logger.js # Sistema de logging ``` --- ## Boas Práticas e Considerações ### Validação de CEP - A biblioteca `cep-promise` realiza consulta em múltiplas bases de dados brasileiras - Retorna erro 502 se o CEP for inválido ou não encontrado ### Distância de Viabilidade - **≤ 500m**: Ambos serviços disponíveis (dedicado e não-dedicado) - **500m - 1000m**: Apenas serviço dedicado disponível - **> 1000m**: Nenhum serviço disponível (retorna "5KM+") ### Criação de Prospectos - O tipo de pessoa é detectado automaticamente: CPF não vazio = Pessoa Física, CNPJ com CPF vazio = Pessoa Jurídica - Números de telefone são sanitizados automaticamente (removem caracteres não-numéricos) - Valores monetários aceitam diversos formatos (R$ 119,90 ou 119.90) ### Segurança - CORS restrito a domínios específicos - Todas as requisições são logadas com IP e método - Erros não expõem informações sensíveis ao cliente --- ## Troubleshooting ### Erro: "CEP não encontrado" - Verifique se o CEP está correto e tem 8 dígitos - Alguns CEPs novos podem não estar na base de dados ### Erro: "Sem caixas dentro de 5km" - Significa que não há ponto de presença próximo ao endereço - O serviço não é viável para esta localização ### Erro: "Plano inválido" - Verifique se a descrição do plano corresponde exatamente a um dos planos mapeados - Referência: [contratacao.service.js:159-170](src/modules/contratacao/contratacao.service.js#L159-L170) ### Logs não aparecem - Verifique se a pasta `logs/` foi criada (criada automaticamente) - Verifique permissões de escrita no diretório do projeto --- ## Histórico de Mudanças ### Recent Updates - ✅ Adicionado tratamento de erro para casos sem caixa em 5km - ✅ Implementada variável de sigla de pasta no .env com mapeamento de provedor - ✅ Refatorada busca de CEP usando `cep-promise` - ✅ Adicionada URL de banda larga na configuração de CORS - ✅ Atualizado suporte de CORS para Express 5.x --- ## Suporte e Contribuições Para reportar bugs ou sugerir melhorias, entre em contato com a equipe de desenvolvimento Sothis. **Contato**: gabriel.amancio@sothis.com.br --- ## Licença ISC