FEAT: Feature de consulta de viabilidade por latitude e longitude.

- Faz a consulta e traz endereço completo.
This commit is contained in:
Gabriel Amancio 2026-01-15 13:43:51 -03:00
parent 2679e86e2e
commit 18787c938b
5 changed files with 105 additions and 5 deletions

View File

@ -15,6 +15,21 @@ async function handleViabilidade(req, res) {
}
}
async function handleViabilidadeLatLong(req, res) {
const { latitude, longitude } = req.body;
logger.info('Recebida requisição de viabilidade por lat/long', { latitude, longitude });
try {
const resultadoViabilidade = await contratacaoService.verificarViabilidadeLatLong(latitude, longitude);
return res.json(resultadoViabilidade);
} catch (error) {
logger.error('Erro no controller ao processar viabilidade por lat/long', { message: error.message, stack: error.stack, latitude, longitude });
const statusCode = error.statusCode || 500;
return res.status(statusCode).json({ error: error.message || "Erro interno ao processar a viabilidade." });
}
}
async function handleCriarProspecto(req, res) {
const prospectData = req.body;
@ -36,7 +51,8 @@ async function handleCriarProspecto(req, res) {
module.exports = {
handleViabilidade,
handleCriarProspecto
handleCriarProspecto,
handleViabilidadeLatLong
};
/*

View File

@ -17,6 +17,16 @@ class ViabilidadeModel {
}
}
class ViabilidadeReverseGeocodeModel {
constructor(endereco, naoDedicado, dedicado, distancia) {
// Inicialização de propriedades do modelo pode ser feita aqui
this.endereco = endereco;
this.naoDedicado = naoDedicado;
this.dedicado = dedicado;
this.distancia = distancia;
}
}
// classe construtor para o modelo de cliente pessoa física e jurídica
class ClientModelPf {
constructor(nome, email, cep, numero, endereco, bairro, cidade, estado, servico, plano, cpf, telefone, tipoPessoa, enderecoCobrança, nomeMae, dataNascimento, diaCobranca, formaPagamento, banco, agencia, conta, emailCobrança) {
@ -143,7 +153,7 @@ class ProspectModel {
}
}
module.exports = {ViabilidadeModel, ClientModelPf, ClientModelPj, ProspectModel};
module.exports = {ViabilidadeReverseGeocodeModel, ViabilidadeModel, ClientModelPf, ClientModelPj, ProspectModel};

View File

@ -5,7 +5,7 @@ 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');
const { ViabilidadeModel, ClientModelPf, ClientModelPj, ProspectModel, ViabilidadeReverseGeocodeModel } = require('./contratacao.model');
// utilitário para ler chaves do payload tolerante a ":" e espaços
const getPayloadValue = (obj, key) => {
@ -124,6 +124,43 @@ async function verificarViabilidade(rawViabilidadeData) {
return viabilidadeResult;
}
async function verificarGeocodeReverso(lat, lon) {
const address = await googleService.reverseGeocodeWithGoogle(lat, lon);
return address;
}
async function verificarViabilidadeLatLong(latitude, longitude) {
const viabilidade = await geogridService.consultaViabilidade(latitude, longitude);
let naoDedicado = false;
let dedicado = false;
if (viabilidade.data && viabilidade.data.distancia !== undefined) {
var distancia = viabilidade.data.distancia;
logger.info(`Distância para o ponto de presença: ${distancia}m`);
if (distancia <= 500) {
naoDedicado = true;
dedicado = true;
} else if (distancia <= 1000) {
naoDedicado = false;
dedicado = true;
}
} else {
naoDedicado = false;
dedicado = false;
var distancia = "5KM+";
logger.warn('Dados de viabilidade não contêm informação de distância', { viabilidadeData: viabilidade.data });
}
const address = await verificarGeocodeReverso(latitude, longitude);
const viabilidadeResult = new ViabilidadeReverseGeocodeModel(address, naoDedicado, dedicado, distancia);
return viabilidadeResult;
}
async function criarProspecto(rawProspectData) {
try {
const payload = (rawProspectData && rawProspectData.prospectData) ? rawProspectData.prospectData : rawProspectData;
@ -229,7 +266,9 @@ async function criarProspecto(rawProspectData) {
module.exports = {
verificarViabilidade,
criarProspecto
criarProspecto,
verificarViabilidadeLatLong,
verificarGeocodeReverso,
};
/*

View File

@ -8,6 +8,9 @@ router.post('/viabilidade', contratacaoController.handleViabilidade);
// Rota para criação de prospecto no Hubsoft
router.post('/prospecto', contratacaoController.handleCriarProspecto);
// Rota para consulta de viabilidade por Lat e Long
router.post('/viabilidade/lat-long', contratacaoController.handleViabilidadeLatLong);
// router.post('/teste', controller.handleTeste);

View File

@ -44,7 +44,39 @@ async function geocodeWithGoogle(address) {
}
}
module.exports = { geocodeWithGoogle };
async function reverseGeocodeWithGoogle(lat, lon) {
const key = apiConfig.googleApiKey;
if (!key) {
logger.error('Chave da API do Google não configurada.');
return null;
}
try {
const url = 'https://maps.googleapis.com/maps/api/geocode/json';
const r = await axios.get(url, {
params: { latlng: `${lat},${lon}`, key },
timeout: 10000,
});
// Valida a resposta e extrai o endereço
if (!r || r.status !== 200) {
logger.warn(`Resposta inesperada do Google Reverse Geocoding API para as coordenadas (${lat}, ${lon})`, { status: r ? r.status : 'undefined' });
return null;
}
if (r.data && Array.isArray(r.data.results) && r.data.results.length > 0) {
const address = r.data.results[0].formatted_address;
return address;
}
logger.warn('Nenhum resultado de reverse geocodificação válido encontrado para as coordenadas', { lat, lon, responseData: r.data });
return null;
} catch (e) {
logger.error(`Erro na chamada ao Google Reverse Geocoding API para as coordenadas (${lat}, ${lon})`, { message: e.message, stack: e.stack });
return null;
}
}
module.exports = { geocodeWithGoogle, reverseGeocodeWithGoogle };
/*
DESCRIÇÃO: