FEAT: Adição de parametros que ainda não estavam indo para o prospecto, e fallback de consultas de CEP.
- Adicionado valor de ID de CRM fixo e ID de origem-cliente fixo para envio do prospecto. - Criado fallback das APIs de consulta de CEP, se caso o ViaCEP falhar, o CepRest assume, mantendo o fluxo fluido. - 5s de timeout adicionados nas requisições para o ViaCep e CepRest. - Logs mais estruturados adicionados.
This commit is contained in:
parent
26fc47f989
commit
2679e86e2e
@ -3,7 +3,7 @@ const logger = require('../../shared/utils/logger.js');
|
|||||||
|
|
||||||
async function handleViabilidade(req, res) {
|
async function handleViabilidade(req, res) {
|
||||||
const rawViabilidadeData = req.body;
|
const rawViabilidadeData = req.body;
|
||||||
|
logger.info('Recebida requisição de viabilidade', { rawViabilidadeData });
|
||||||
try {
|
try {
|
||||||
const resultadoViabilidade = await contratacaoService.verificarViabilidade(rawViabilidadeData);
|
const resultadoViabilidade = await contratacaoService.verificarViabilidade(rawViabilidadeData);
|
||||||
return res.json(resultadoViabilidade);
|
return res.json(resultadoViabilidade);
|
||||||
@ -20,6 +20,10 @@ async function handleCriarProspecto(req, res) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const resultado = await contratacaoService.criarProspecto(prospectData);
|
const resultado = await contratacaoService.criarProspecto(prospectData);
|
||||||
|
if (resultado.status === 'error') {
|
||||||
|
logger.error('Erro ao criar prospecto', { resultado });
|
||||||
|
return res.status(500).json({ error: resultado.msg || "Erro ao criar o prospecto." });
|
||||||
|
}
|
||||||
logger.info('Prospecto criado com sucesso', { resultado });
|
logger.info('Prospecto criado com sucesso', { resultado });
|
||||||
return res.json({ message: 'Prospecto criado com sucesso', data: resultado });
|
return res.json({ message: 'Prospecto criado com sucesso', data: resultado });
|
||||||
|
|
||||||
|
|||||||
@ -73,20 +73,29 @@ class ClientModelPj {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProspectModel {
|
class ProspectModel {
|
||||||
constructor(cep, servico, nomeRazaoSocial, cpfCnpj, telefone, email, tipoPessoa, bairro, endereco, numero, nomeMae, idCrm, complemento, dataNascimento) {
|
// ordem: cep, servico, nomeRazaoSocial, cpfCnpj, telefone, email, tipoPessoa,
|
||||||
|
// bairro, endereco, numero, nomeMae, idCrm, complemento, dataNascimento
|
||||||
|
constructor(cep, servico, nomeRazaoSocial, cpfCnpj, telefone, email, tipoPessoa, bairro, endereco, numero, nomeMae, complemento, dataNascimento) {
|
||||||
this.cep = cep;
|
this.cep = cep;
|
||||||
this.servico = servico;
|
this.servico = servico;
|
||||||
this.cpf_cnpj = cpfCnpj;
|
this.cpf_cnpj = cpfCnpj;
|
||||||
this.telefone = telefone;
|
this.telefone = telefone;
|
||||||
this.nome_razaosocial = nomeRazaoSocial;
|
this.nome_razaosocial = nomeRazaoSocial;
|
||||||
|
// manter ambos formatos (snake e camel) para compatibilidade
|
||||||
|
this.tipo_pessoa = tipoPessoa;
|
||||||
this.tipoPessoa = tipoPessoa;
|
this.tipoPessoa = tipoPessoa;
|
||||||
|
|
||||||
this.bairro = bairro;
|
this.bairro = bairro;
|
||||||
this.endereco = endereco;
|
this.endereco = endereco;
|
||||||
this.numero = numero;
|
this.numero = numero;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
|
|
||||||
|
this.nome_mae = nomeMae;
|
||||||
this.nomeMae = nomeMae;
|
this.nomeMae = nomeMae;
|
||||||
this.id_crm = idCrm;
|
|
||||||
this.complemento = complemento;
|
this.complemento = complemento;
|
||||||
|
|
||||||
|
this.data_nascimento = dataNascimento;
|
||||||
this.dataNascimento = dataNascimento;
|
this.dataNascimento = dataNascimento;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,18 +106,19 @@ class ProspectModel {
|
|||||||
id_servico: this.servico.id_servico ?? this.servico.id ?? null,
|
id_servico: this.servico.id_servico ?? this.servico.id ?? null,
|
||||||
valor: this.servico.valor ?? null
|
valor: this.servico.valor ?? null
|
||||||
} : null,
|
} : null,
|
||||||
|
nome_razaosocial: this.nome_razaosocial,
|
||||||
cpf_cnpj: this.cpf_cnpj,
|
cpf_cnpj: this.cpf_cnpj,
|
||||||
telefone: this.telefone,
|
telefone: this.telefone,
|
||||||
nome_razaosocial: this.nome_razaosocial,
|
|
||||||
tipo_pessoa: this.tipoPessoa,
|
|
||||||
bairro: this.bairro,
|
|
||||||
numero: this.numero,
|
|
||||||
endereco: this.endereco,
|
|
||||||
email: this.email,
|
email: this.email,
|
||||||
nome_mae: this.nomeMae,
|
tipo_pessoa: this.tipo_pessoa,
|
||||||
id_crm: this.id_crm,
|
bairro: this.bairro,
|
||||||
|
endereco: this.endereco,
|
||||||
|
numero: this.numero,
|
||||||
|
nome_mae: this.nome_mae,
|
||||||
|
id_crm: 4,
|
||||||
|
data_nascimento: this.data_nascimento,
|
||||||
complemento: this.complemento,
|
complemento: this.complemento,
|
||||||
data_nascimento: this.dataNascimento
|
id_origem_cliente: 51
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pjToJSON() {
|
pjToJSON() {
|
||||||
@ -122,11 +132,13 @@ class ProspectModel {
|
|||||||
cpf_cnpj: this.cpf_cnpj,
|
cpf_cnpj: this.cpf_cnpj,
|
||||||
telefone: this.telefone,
|
telefone: this.telefone,
|
||||||
email: this.email,
|
email: this.email,
|
||||||
tipo_pessoa: this.tipoPessoa,
|
tipo_pessoa: this.tipo_pessoa,
|
||||||
|
id_crm: 4,
|
||||||
bairro: this.bairro,
|
bairro: this.bairro,
|
||||||
endereco: this.endereco,
|
endereco: this.endereco,
|
||||||
numero: this.numero,
|
numero: this.numero,
|
||||||
complemento: this.complemento
|
complemento: this.complemento,
|
||||||
|
id_origem_cliente: 51
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
const geogridService = require("../../shared/apis/geogridService.js");
|
const geogridService = require("../../shared/apis/geogridService.js");
|
||||||
const googleService = require("../../shared/apis/googleService.js");
|
const googleService = require("../../shared/apis/googleService.js");
|
||||||
// const cepRestService = require("../../shared/apis/cepRestService.js");
|
const cepRestService = require("../../shared/apis/cepRestService.js");
|
||||||
const hubsoftService = require("../../shared/apis/hubsoftService.js");
|
const hubsoftService = require("../../shared/apis/hubsoftService.js");
|
||||||
const logger = require('../../shared/utils/logger.js');
|
const logger = require('../../shared/utils/logger.js');
|
||||||
const repository = require('./contratacao.repository.js');
|
const repository = require('./contratacao.repository.js');
|
||||||
const viaCepService = require("../../shared/apis/viaCepService.js");
|
const viaCepService = require("../../shared/apis/viaCepService.js");
|
||||||
const {ViabilidadeModel, ClientModelPf, ClientModelPj, ProspectModel} = require('./contratacao.model');
|
const { ViabilidadeModel, ClientModelPf, ClientModelPj, ProspectModel } = require('./contratacao.model');
|
||||||
|
|
||||||
// utilitário para ler chaves do payload tolerante a ":" e espaços
|
// utilitário para ler chaves do payload tolerante a ":" e espaços
|
||||||
const getPayloadValue = (obj, key) => {
|
const getPayloadValue = (obj, key) => {
|
||||||
@ -37,36 +37,45 @@ class ServiceError extends Error {
|
|||||||
async function verificarViabilidade(rawViabilidadeData) {
|
async function verificarViabilidade(rawViabilidadeData) {
|
||||||
const rawCep = rawViabilidadeData.cep;
|
const rawCep = rawViabilidadeData.cep;
|
||||||
const rawNumero = rawViabilidadeData.numero;
|
const rawNumero = rawViabilidadeData.numero;
|
||||||
|
const source = rawViabilidadeData.source || '';
|
||||||
|
|
||||||
|
let address;
|
||||||
|
let addressString;
|
||||||
|
|
||||||
if (!rawCep || !rawNumero) {
|
if (!rawCep || !rawNumero) {
|
||||||
logger.warn('CEP ou número não fornecidos na verificação de viabilidade.');
|
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);
|
throw new ServiceError('CEP e número são obrigatórios.', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consulta o endereço completo usando a API externa de CEP
|
// Obtém o endereço completo usando a API de CEP (viaCEP e cepRestService como fallback)
|
||||||
const addressData = await viaCepService.getConsultaCep(rawCep);
|
try {
|
||||||
if (!addressData) {
|
address = await viaCepService.getConsultaCep(rawCep);
|
||||||
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);
|
if (!address || !address.logradouro) {
|
||||||
|
throw new Error('Resposta inválida do viaCEP');
|
||||||
|
}
|
||||||
|
logger.info('Endereço obtido com sucesso via viaCEP', { address });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
address = await cepRestService.getConsultaCep(rawCep);
|
||||||
|
if (!address || !address.logradouro) {
|
||||||
|
throw new Error('Resposta inválida do cepRestService');
|
||||||
|
}
|
||||||
|
logger.info('Endereço obtido com sucesso via cepRestService', { address });
|
||||||
}
|
}
|
||||||
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
|
if (!address) {
|
||||||
const addressString = `${logradouro}, ${rawNumero}, ${bairro}, ${city}, ${state}, ${cep}`;
|
throw new ServiceError('Não foi possível obter endereço para o CEP informado.', 502);
|
||||||
logger.info('String de endereço montada para geocodificação', { addressString });
|
}
|
||||||
|
|
||||||
|
|
||||||
// const address = await cepRestService.getConsultaCep(rawCep);
|
// Obtém as coordenadas geográficas do endereço usando o Google Geocoding API
|
||||||
// // FIX: Revertendo para a verificação correta da resposta do cepRestService
|
|
||||||
// if (!address) {
|
const { logradouro, bairro, localidade: city, uf: state, cep } = address;
|
||||||
// logger.warn('Endereço não encontrado ou resposta inválida do serviço de CEP', { cep: rawCep, response: address });
|
|
||||||
// throw new ServiceError('Endereço não encontrado para o CEP fornecido.', 404);
|
addressString = `${logradouro}, ${rawNumero}, ${bairro}, ${city}, ${state}, ${cep}`;
|
||||||
// }
|
logger.info('Endereço montado para geocodificação', { addressString });
|
||||||
// logger.info('Endereço obtido com sucesso via CEP', { data: address });
|
|
||||||
|
|
||||||
// const { logradouro, bairro, localidade: city, uf: state, cep } = address; // 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 coords = await googleService.geocodeWithGoogle(addressString);
|
const coords = await googleService.geocodeWithGoogle(addressString);
|
||||||
if (!coords) {
|
if (!coords) {
|
||||||
@ -97,15 +106,20 @@ async function verificarViabilidade(rawViabilidadeData) {
|
|||||||
logger.warn('Dados de viabilidade não contêm informação de distância', { viabilidadeData: viabilidade.data });
|
logger.warn('Dados de viabilidade não contêm informação de distância', { viabilidadeData: viabilidade.data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const viabilidadeResult = new ViabilidadeModel(rawViabilidadeData.nome, rawViabilidadeData.email, rawViabilidadeData.telefone, logradouro, rawNumero, bairro, city, state, cep, naoDedicado, dedicado, distancia || null);
|
const viabilidadeResult = new ViabilidadeModel(rawViabilidadeData.nome, rawViabilidadeData.email, rawViabilidadeData.telefone, logradouro, rawNumero, bairro, city, state, cep, naoDedicado, dedicado, distancia || null);
|
||||||
|
|
||||||
await repository.insertViabilidadeData(viabilidadeResult)
|
if (source) {
|
||||||
.then(() => {
|
return viabilidadeResult;
|
||||||
logger.info('Dados de viabilidade inseridos no repositório com sucesso', { viabilidadeResult });
|
}
|
||||||
})
|
|
||||||
.catch((err) => {
|
try {
|
||||||
logger.error('Erro ao inserir dados de viabilidade no repositório', { message: err.message, stack: err.stack });
|
await repository.insertViabilidadeData(viabilidadeResult);
|
||||||
});
|
logger.info('Viabilidade salva com sucesso');
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('Erro ao salvar viabilidade', err);
|
||||||
|
}
|
||||||
|
|
||||||
return viabilidadeResult;
|
return viabilidadeResult;
|
||||||
}
|
}
|
||||||
@ -115,11 +129,11 @@ async function criarProspecto(rawProspectData) {
|
|||||||
const payload = (rawProspectData && rawProspectData.prospectData) ? rawProspectData.prospectData : rawProspectData;
|
const payload = (rawProspectData && rawProspectData.prospectData) ? rawProspectData.prospectData : rawProspectData;
|
||||||
|
|
||||||
const planos = {
|
const planos = {
|
||||||
'100 Mega + Super WiFi': { id_servico: '22'},
|
'100 Mega + Super WiFi': { id_servico: '22' },
|
||||||
'200 Mega + Super WiFi': { id_servico: '94'},
|
'200 Mega + Super WiFi': { id_servico: '94' },
|
||||||
'500 Mega + Super WiFi': { id_servico: '96'},
|
'500 Mega + Super WiFi': { id_servico: '96' },
|
||||||
'700 Mega + Super WiFi': { id_servico: '97'},
|
'700 Mega + Super WiFi': { id_servico: '97' },
|
||||||
'1 Gb + Super WiFi': { id_servico: '32'},
|
'1 Gb + Super WiFi': { id_servico: '32' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const planoKey = getPayloadValue(payload, 'Descrição');
|
const planoKey = getPayloadValue(payload, 'Descrição');
|
||||||
@ -144,21 +158,30 @@ async function criarProspecto(rawProspectData) {
|
|||||||
throw new ServiceError('Plano inválido ou não encontrado.', 400);
|
throw new ServiceError('Plano inválido ou não encontrado.', 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//função que troca a / da data de nascimento por -
|
||||||
|
const formatDate = (dateStr) => {
|
||||||
|
if (!dateStr) return "";
|
||||||
|
return dateStr.replace(/\//g, '-');
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataNascimento = formatDate(getPayloadValue(payload, 'Data de nascimento') || "");
|
||||||
|
|
||||||
if (payload["CPF:"] === "") {
|
if (payload["CPF:"] === "") {
|
||||||
// Pessoa Jurídica
|
// Pessoa Jurídica
|
||||||
const prospectData = new ProspectModel(
|
const prospectData = new ProspectModel(
|
||||||
getPayloadValue(payload, 'CEP'),
|
getPayloadValue(payload, 'CEP'),
|
||||||
servico, // passa o objeto { id_servico, valor }
|
servico, // objeto { id_servico, valor }
|
||||||
getPayloadValue(payload, 'Razão Social'),
|
getPayloadValue(payload, 'Razão Social'), // nomeRazaoSocial
|
||||||
getPayloadValue(payload, 'CNPJ'),
|
getPayloadValue(payload, 'CNPJ'), // cpfCnpj
|
||||||
celular,
|
celular, // telefone
|
||||||
getPayloadValue(payload, 'E-mail'),
|
getPayloadValue(payload, 'E-mail'), // email
|
||||||
"pj",
|
"pj", // tipoPessoa
|
||||||
getPayloadValue(payload, 'Bairro'),
|
getPayloadValue(payload, 'Bairro'), // bairro
|
||||||
getPayloadValue(payload, 'Logradouro'),
|
getPayloadValue(payload, 'Logradouro'), // endereco
|
||||||
getPayloadValue(payload, 'Número'),
|
getPayloadValue(payload, 'Número'), // numero
|
||||||
4, // ID fixo do CRM Vendas
|
"", // nomeMae (não aplicável para PJ)
|
||||||
getPayloadValue(payload, 'Complemento') || ""
|
getPayloadValue(payload, 'Complemento') || "", // complemento
|
||||||
|
"" // dataNascimento (não aplicável)
|
||||||
);
|
);
|
||||||
console.log(prospectData);
|
console.log(prospectData);
|
||||||
// serializa para JSON plano conforme toJSON()
|
// serializa para JSON plano conforme toJSON()
|
||||||
@ -169,22 +192,21 @@ async function criarProspecto(rawProspectData) {
|
|||||||
await hubsoftService.criarProspectHubsoft(prospectPayload);
|
await hubsoftService.criarProspectHubsoft(prospectPayload);
|
||||||
return prospectPayload;
|
return prospectPayload;
|
||||||
} else {
|
} else {
|
||||||
// clientData não sendo usado, pois o e-mail está sendo enviado pelo frontend.
|
// Pessoa Física
|
||||||
const prospectData = new ProspectModel(
|
const prospectData = new ProspectModel(
|
||||||
getPayloadValue(payload, 'CEP'),
|
getPayloadValue(payload, 'CEP'),
|
||||||
servico, // passa o objeto { id_servico, valor }
|
servico, // objeto { id_servico, valor }
|
||||||
getPayloadValue(payload, 'Nome completo'),
|
getPayloadValue(payload, 'Nome completo'), // nomeRazaoSocial
|
||||||
getPayloadValue(payload, 'CPF'),
|
getPayloadValue(payload, 'CPF'), // cpfCnpj
|
||||||
celular,
|
celular, // telefone
|
||||||
getPayloadValue(payload, 'E-mail'),
|
getPayloadValue(payload, 'E-mail'), // email
|
||||||
"pf",
|
"pf", // tipoPessoa
|
||||||
getPayloadValue(payload, 'Bairro'),
|
getPayloadValue(payload, 'Bairro'), // bairro
|
||||||
getPayloadValue(payload, 'Logradouro'),
|
getPayloadValue(payload, 'Logradouro'), // endereco
|
||||||
getPayloadValue(payload, 'Número'),
|
getPayloadValue(payload, 'Número'), // numero
|
||||||
getPayloadValue(payload, 'Nome da mãe') || "",
|
getPayloadValue(payload, 'Nome da mãe') || "", // nomeMae
|
||||||
4, // ID fixo do CRM Vendas
|
getPayloadValue(payload, 'Complemento') || "", // complemento
|
||||||
getPayloadValue(payload, 'Complemento') || "",
|
dataNascimento // dataNascimento
|
||||||
getPayloadValue(payload, 'Data de nascimento') || ""
|
|
||||||
);
|
);
|
||||||
console.log(prospectData);
|
console.log(prospectData);
|
||||||
// serializa para JSON plano conforme toJSON()
|
// serializa para JSON plano conforme toJSON()
|
||||||
@ -193,10 +215,10 @@ async function criarProspecto(rawProspectData) {
|
|||||||
: JSON.parse(JSON.stringify(prospectData));
|
: JSON.parse(JSON.stringify(prospectData));
|
||||||
|
|
||||||
// envia objeto plano ao hubsoft (o hubsoftService já monta { prospectData })
|
// envia objeto plano ao hubsoft (o hubsoftService já monta { prospectData })
|
||||||
await hubsoftService.criarProspectHubsoft(prospectPayload);
|
const result = await hubsoftService.criarProspectHubsoft(prospectPayload);
|
||||||
|
|
||||||
logger.info('Criando prospecto PF', { prospectPayload });
|
logger.info('Criando prospecto PF', { prospectPayload });
|
||||||
return prospectPayload;
|
return result;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error('Erro ao criar prospecto', { message: error.message, stack: error.stack });
|
logger.error('Erro ao criar prospecto', { message: error.message, stack: error.stack });
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const getConsultaCep = async (rawCep) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const cepRestUrl = 'https://api.cep.rest/';
|
const cepRestUrl = 'https://api.cep.rest/';
|
||||||
const address = await axios.post(cepRestUrl, { cep });
|
const address = await axios.post(cepRestUrl, { cep }, { timeout: 5000 });
|
||||||
console.log(address.data);
|
console.log(address.data);
|
||||||
|
|
||||||
// Tratamento de resposta conforme diferentes estruturas possíveis
|
// Tratamento de resposta conforme diferentes estruturas possíveis
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const getConsultaCep = async (rawCep) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const viaCepUrl = `https://viacep.com.br/ws/${cep}/json/`;
|
const viaCepUrl = `https://viacep.com.br/ws/${cep}/json/`;
|
||||||
const response = await axios.get(viaCepUrl);
|
const response = await axios.get(viaCepUrl, { timeout: 5000 });
|
||||||
if (response.data.erro) {
|
if (response.data.erro) {
|
||||||
logger.warn('CEP não encontrado na API ViaCEP', { cep });
|
logger.warn('CEP não encontrado na API ViaCEP', { cep });
|
||||||
return null; // Controller tratará como 'Endereço não encontrado'
|
return null; // Controller tratará como 'Endereço não encontrado'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user