2025-11-24 16:13:55 -03:00
# Sothis Contratação API
## Visão Geral
2026-07-20 09:44:06 -03:00
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.
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
### Funcionalidades Principais
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
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.
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
## Features Técnicas
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
- **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` .
2025-11-24 16:13:55 -03:00
## Pré-requisitos
- Node.js (versão 18.x ou superior recomendada)
- npm (geralmente instalado junto com o Node.js)
2026-07-20 09:44:06 -03:00
- PostgreSQL (opcional, para persistência de dados)
- Chaves de API: Google Maps, GeoGrid, Hubsoft
2025-11-24 16:13:55 -03:00
## 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)
2026-07-20 09:44:06 -03:00
### Variáveis de Ambiente Obrigatórias
2025-11-24 16:13:55 -03:00
```env
2026-07-20 09:44:06 -03:00
# Servidor
2025-11-24 16:13:55 -03:00
PORT=3000
2026-07-20 09:44:06 -03:00
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
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
# 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
2025-11-24 16:13:55 -03:00
```
2026-07-23 07:35:52 -03:00
### Classificação de Pastas (provedor)
O provedor é resolvido pelo **prefixo da sigla da pasta** no GeoGrid (não há configuração no `.env` ):
2026-07-20 09:44:06 -03:00
2026-07-23 07:35:52 -03:00
- `s-...` → **Sothis** (rede própria).
- `p-<nome>...` → **parceiro** ; o provedor é o nome que vem depois do `-` (ex.: `p-Vivo` → `Vivo` ).
2026-07-23 09:57:43 -03:00
- **Meio de transmissão** (marcador logo após o prefixo):
- `sub` → rede **subterrânea** , prefixa `(Subterrâneo)` (ex.: `s-sub-Barueri` → `(Subterrâneo) Sothis` ).
- `a` → **Aéreo** , sufixa ` - Aéreo` (ex.: `S-A-ABC` → `Sothis - Aéreo` ).
- `r` → **Rádio** , sufixa ` - Rádio` (ex.: `P-R-Vivo` → `Vivo - Rádio` ).
2026-07-23 07:35:52 -03:00
- Qualquer sigla fora dessa convenção é considerada **não elegível** (ignorada).
2026-07-20 09:44:06 -03:00
2025-11-24 16:13:55 -03:00
## 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
```
2026-07-20 09:44:06 -03:00
A API será iniciada na porta configurada (padrão `3000` ) e exibirá:
```
🚀 Servidor API rodando na porta 3000 em modo development
```
2025-11-24 16:13:55 -03:00
### 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
```
---
2026-07-20 09:44:06 -03:00
## 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 ).
---
2025-11-24 16:13:55 -03:00
## Documentação da API
O prefixo para todos os endpoints é `/api` .
2026-07-20 09:44:06 -03:00
### 1. Consulta de Viabilidade por CEP
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
Verifica a viabilidade técnica de um endereço usando CEP e número.
2025-11-24 16:13:55 -03:00
- **Endpoint** : `POST /viabilidade`
2026-07-20 09:44:06 -03:00
- **Descrição** : Realiza geocodificação do endereço e consulta viabilidade na GeoGrid baseado em pontos de presença.
2025-11-24 16:13:55 -03:00
- **Corpo da Requisição** (`application/json`):
```json
{
2026-07-20 09:44:06 -03:00
"nome": "João Silva",
"email": "joao@email.com",
"telefone": "11987654321",
2025-11-24 16:13:55 -03:00
"cep": "06419240",
2026-07-20 09:44:06 -03:00
"numero": "303",
"source": ""
2025-11-24 16:13:55 -03:00
}
```
- **Resposta de Sucesso** (`200 OK`):
```json
{
2026-07-20 09:44:06 -03:00
"nome": "João Silva",
"email": "joao@email.com",
"telefone": "11987654321",
"logradouro": "Rua Imirim",
"numero": "303",
2025-11-24 16:13:55 -03:00
"bairro": "Chácaras Marco",
"cidade": "Barueri",
"estado": "SP",
2026-07-20 09:44:06 -03:00
"cep": "06419240",
2025-11-24 16:13:55 -03:00
"naoDedicado": true,
2026-07-20 09:44:06 -03:00
"dedicado": true,
"distancia": 250,
"provedor": "Sothis"
2025-11-24 16:13:55 -03:00
}
```
2026-07-20 09:44:06 -03:00
**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).
2026-07-23 07:35:52 -03:00
- `provedor` : Identificação do provedor pela convenção de prefixo da sigla de pasta (ver "Classificação de Pastas")
2026-07-20 09:44:06 -03:00
> **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.
2025-11-24 16:13:55 -03:00
- **Respostas de Erro** :
- `400 Bad Request` : Se `cep` ou `numero` não forem fornecidos.
2026-07-20 09:44:06 -03:00
- `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).
---
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
### 2. Consulta de Viabilidade por Coordenadas
2025-11-24 16:13:55 -03:00
2026-07-20 09:44:06 -03:00
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.
2025-11-24 16:13:55 -03:00
- **Endpoint** : `POST /prospecto`
2026-07-20 09:44:06 -03:00
- **Descrição** : Registra um novo prospecto no sistema Hubsoft com dados de contato e plano selecionado.
2025-11-24 16:13:55 -03:00
- **Corpo da Requisição** (`application/json`):
2026-07-20 09:44:06 -03:00
**Para Pessoa Física (CPF não vazio)** :
2025-11-24 16:13:55 -03:00
```json
{
2026-07-20 09:44:06 -03:00
"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"
}
2025-11-24 16:13:55 -03:00
}
```
2026-07-20 09:44:06 -03:00
**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`
2025-11-24 16:13:55 -03:00
- **Resposta de Sucesso** (`200 OK`):
```json
{
"message": "Prospecto criado com sucesso",
"data": {
2026-07-20 09:44:06 -03:00
"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
}
2025-11-24 16:13:55 -03:00
}
}
```
- **Respostas de Erro** :
2026-07-20 09:44:06 -03:00
- `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