FEAT: Implementar serviço viaCep para consulta de CEP secundário e tratamento de consulta de pastas do Geogrid.

This commit is contained in:
Gabriel Amancio 2025-12-15 13:26:40 -03:00
parent 50935d43e7
commit 1ae5a18317
5 changed files with 108 additions and 2 deletions

51
src/ecosystem.config.js Normal file
View File

@ -0,0 +1,51 @@
module.exports = {
apps: [
// 🟢 --- PRIMEIRA APLICAÇÃO: API PRINCIPAL (servidor HTTP) ---
{
name: "contratacao-sothis-api", // Nome que aparecerá no PM2
script: "./app.js", // Caminho do arquivo principal da API
// 👇 Execução em modo "cluster" (um processo por core da máquina)
exec_mode: "cluster",
instances: "max", // "max" = usa todos os núcleos disponíveis
// ⚙️ Variáveis de ambiente padrão (modo development)
env: {
watch: true,
NODE_ENV: "development",
PORT: 3000 // Porta usada no ambiente de desenvolvimento
},
// ⚙️ Variáveis de ambiente quando rodar com `--env production`
env_production: {
watch: false,
NODE_ENV: "production",
PORT: 8080 // Porta usada no ambiente de produção
}
},
]
};
/** * @module server
* @description Ponto de entrada principal da aplicação.
* Este módulo é responsável por:
* Definir a configuração do PM2 para gerenciar a aplicação principal e o serviço de cron jobs.
* 1. A aplicação principal (`hubxglpi-api`) roda em modo cluster para lidar com requisições HTTP. Para encerrar chamados.
* 2. O serviço de cron jobs (`hubxglpi-cron`) roda em modo fork para evitar execuções duplicadas das tarefas agendadas.
*/
/**
* 💡 Dicas de uso:
*
* 🧪 Ambiente de desenvolvimento:
* pm2 start ecosystem.config.js --env development
*
* 🚀 Ambiente de produção:
* pm2 start ecosystem.config.js --env production
* pm2 startup systemd
* sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u desenvolvimento --hp /home/desenvolvimento
* pm2 save
*
* Após isso, o PM2 inicializa automaticamente os dois processos no boot do servidor.
*/

View File

@ -4,6 +4,7 @@ const cepRestService = require("../../shared/apis/cepRestService.js");
const hubsoftService = require("../../shared/apis/hubsoftService.js");
const logger = require('../../shared/utils/logger.js');
const repository = require('./contratacao.repository.js');
// const viaCepService = require("../../shared/apis/viaCepService.js");
const {ViabilidadeModel, ClientModelPf, ClientModelPj, ProspectModel} = require('./contratacao.model');
// utilitário para ler chaves do payload tolerante a ":" e espaços
@ -41,7 +42,20 @@ async function verificarViabilidade(rawViabilidadeData) {
logger.warn('CEP ou número não fornecidos na verificação de viabilidade.');
throw new ServiceError('CEP e número são obrigatórios.', 400);
}
// // Consulta o endereço completo usando a API externa de CEP
// const addressData = await viaCepService.getConsultaCep(rawCep);
// if (!addressData) {
// logger.warn('Endereço não encontrado ou resposta inválida do serviço de CEP', { cep: rawCep, response: addressData });
// throw new ServiceError('Endereço não encontrado para o CEP fornecido.', 404);
// }
// logger.info('Endereço obtido com sucesso via CEP', { data: addressData });
// const { logradouro, bairro, localidade: city, uf: state, cep } = addressData; // FIX: Usar address.data para desestruturar
// const addressString = `${logradouro}, ${rawNumero}, ${bairro}, ${city}, ${state}, ${cep}`;
// logger.info('String de endereço montada para geocodificação', { addressString });
const address = await cepRestService.getConsultaCep(rawCep);
// FIX: Revertendo para a verificação correta da resposta do cepRestService
if (!address) {

View File

@ -20,6 +20,9 @@ const getConsultaCep = async (rawCep) => {
try {
const cepRestUrl = 'https://api.cep.rest/';
const address = await axios.post(cepRestUrl, { cep });
console.log(address.data);
// Tratamento de resposta conforme diferentes estruturas possíveis
if (address.data && address.data.code === 404) {
logger.warn('CEP não encontrado na API externa', { cep, response: address.data });

View File

@ -19,6 +19,7 @@ const consultaViabilidade = async (lat, lon) => {
"itens[]": "caixa",
ordenarCampos: ["distancia"],
ordenarPor: ["asc"],
consultarPasta: "S",
consultarIndividual: "S"
};
@ -35,8 +36,15 @@ const consultaViabilidade = async (lat, lon) => {
}
});
// Extrai o primeiro registro da resposta em que a pasta.sigla seja "São Bernardo do Campo - SP", "São Paulo - SP", "Barueri - São Paulo" e "TMC" descartar os demais
const registros = response.data && response.data.registros;
const primeiro = Array.isArray(registros) && registros.length ? registros[0] : null;
const registrosFiltrados = registros.filter(r => {
const sigla = r.pasta && r.pasta.sigla;
return sigla === "São Bernardo do Campo - SP" || sigla === "São Paulo - SP" || sigla === "Barueri - São Paulo" || sigla === "TMC";
});
const primeiro = registrosFiltrados[0];
// Retorna no formato esperado pelo controller (viabilidade.data.distancia)
return { data: primeiro };

View File

@ -0,0 +1,30 @@
const axios = require("axios");
const logger = require('../utils/logger.js');
const getConsultaCep = async (rawCep) => {
logger.info('Iniciando consulta de CEP');
if (!rawCep) {
logger.warn('CEP não fornecido para getConsultaCep');
throw new Error("cep é obrigatório");
}
const cep = String(rawCep).trim().replace(/\D/g, "");
if (cep.length !== 8) {
logger.warn('CEP inválido fornecido para getConsultaCep', { cepBruto: rawCep, cepLimpo: cep });
throw new Error("cep inválido, verifique se foram digitados apenas números");
}
try {
const viaCepUrl = `https://viacep.com.br/ws/${cep}/json/`;
const response = await axios.get(viaCepUrl);
if (response.data.erro) {
logger.warn('CEP não encontrado na API ViaCEP', { cep });
return null; // Controller tratará como 'Endereço não encontrado'
} else {
return response.data;
}
} catch (error) {
logger.error("Erro na chamada da API ViaCEP", { message: error.message, stack: error.stack, cep });
throw new Error("Erro ao consultar o CEP");
}
};
module.exports = { getConsultaCep };