FEAT: Ajustado para uso da geolocalização antes do CEP
This commit is contained in:
parent
e42621642b
commit
5b98394ee2
@ -117,7 +117,8 @@ function hasAddressOrNumberHeader(headers) {
|
|||||||
|
|
||||||
function hasGeoHeaders(headers) {
|
function hasGeoHeaders(headers) {
|
||||||
const normalizedHeaders = headers.map(normalizeHeader);
|
const normalizedHeaders = headers.map(normalizeHeader);
|
||||||
return normalizedHeaders.includes('latitude') && normalizedHeaders.includes('longitude');
|
return normalizedHeaders.some(header => header.includes('latitude'))
|
||||||
|
&& normalizedHeaders.some(header => header.includes('longitude'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function findHeaderRowIndex(rows) {
|
function findHeaderRowIndex(rows) {
|
||||||
@ -136,8 +137,8 @@ function resolveColumnIndexes(headers) {
|
|||||||
idxCep: findFirstHeaderIndex(headers, header => /\bcep\b/.test(header) || header === 'codigo postal'),
|
idxCep: findFirstHeaderIndex(headers, header => /\bcep\b/.test(header) || header === 'codigo postal'),
|
||||||
idxNumero: exactIndex(['numero', 'número', 'num', 'nº', 'n°']),
|
idxNumero: exactIndex(['numero', 'número', 'num', 'nº', 'n°']),
|
||||||
idxEndereco: findFirstHeaderIndex(headers, header => header.includes('endereco') || header.includes('logradouro')),
|
idxEndereco: findFirstHeaderIndex(headers, header => header.includes('endereco') || header.includes('logradouro')),
|
||||||
idxLatitude: exactIndex(['latitude']),
|
idxLatitude: findFirstHeaderIndex(headers, header => header.includes('latitude')),
|
||||||
idxLongitude: exactIndex(['longitude'])
|
idxLongitude: findFirstHeaderIndex(headers, header => header.includes('longitude'))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,13 +171,52 @@ function buildCepPayload(cols, indexes) {
|
|||||||
return { cep, numero };
|
return { cep, numero };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseCoordinate(value) {
|
||||||
|
const parsed = parseFloat(String(value ?? '').trim().replace(',', '.'));
|
||||||
|
return Number.isFinite(parsed) ? parsed : NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildGeoPayload(cols, indexes) {
|
||||||
|
const latitude = indexes.idxLatitude >= 0 ? parseCoordinate(cols[indexes.idxLatitude]) : NaN;
|
||||||
|
const longitude = indexes.idxLongitude >= 0 ? parseCoordinate(cols[indexes.idxLongitude]) : NaN;
|
||||||
|
|
||||||
|
if (isNaN(latitude) || isNaN(longitude)) return null;
|
||||||
|
return { latitude, longitude };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function consultarComFallback(geoPayload, cepPayload) {
|
||||||
|
let lastError = null;
|
||||||
|
|
||||||
|
if (geoPayload) {
|
||||||
|
try {
|
||||||
|
const result = await consultarViabilidade(geoPayload);
|
||||||
|
if (!result || !result.error) return result;
|
||||||
|
lastError = new Error(result.error);
|
||||||
|
} catch (err) {
|
||||||
|
lastError = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cepPayload) {
|
||||||
|
try {
|
||||||
|
const result = await consultarViabilidade(cepPayload);
|
||||||
|
if (!result || !result.error) return result;
|
||||||
|
lastError = new Error(result.error);
|
||||||
|
} catch (err) {
|
||||||
|
lastError = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw lastError || new Error('Linha sem latitude/longitude ou CEP valido');
|
||||||
|
}
|
||||||
|
|
||||||
function cleanCsvValue(value) {
|
function cleanCsvValue(value) {
|
||||||
const text = String(value ?? '').replace(/[\r\n;]/g, ' ');
|
const text = String(value ?? '').replace(/[\r\n;]/g, ' ');
|
||||||
return text.includes('"') ? text.replace(/"/g, "'") : text;
|
return text.includes('"') ? text.replace(/"/g, "'") : text;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function countValidLines(inputPath) {
|
async function countValidLines(inputPath) {
|
||||||
const dataType = await discoverDataType(inputPath);
|
await discoverDataType(inputPath);
|
||||||
const rows = readRows(inputPath);
|
const rows = readRows(inputPath);
|
||||||
const headerRowIndex = findHeaderRowIndex(rows);
|
const headerRowIndex = findHeaderRowIndex(rows);
|
||||||
const headers = rows[headerRowIndex] || [];
|
const headers = rows[headerRowIndex] || [];
|
||||||
@ -184,20 +224,16 @@ async function countValidLines(inputPath) {
|
|||||||
let total = 0;
|
let total = 0;
|
||||||
|
|
||||||
for (const cols of rows.slice(headerRowIndex + 1)) {
|
for (const cols of rows.slice(headerRowIndex + 1)) {
|
||||||
if (dataType === 'cep') {
|
const geoPayload = buildGeoPayload(cols, indexes);
|
||||||
if (buildCepPayload(cols, indexes)) total++;
|
const cepPayload = buildCepPayload(cols, indexes);
|
||||||
} else if (dataType === 'geolocalizacao') {
|
if (geoPayload || cepPayload) total++;
|
||||||
const latitude = indexes.idxLatitude >= 0 ? parseFloat(cols[indexes.idxLatitude]) : NaN;
|
|
||||||
const longitude = indexes.idxLongitude >= 0 ? parseFloat(cols[indexes.idxLongitude]) : NaN;
|
|
||||||
if (!isNaN(latitude) && !isNaN(longitude)) total++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processCsvFile(jobId, inputPath, originalName) {
|
async function processCsvFile(jobId, inputPath, originalName) {
|
||||||
const dataType = await discoverDataType(inputPath);
|
await discoverDataType(inputPath);
|
||||||
const rows = readRows(inputPath);
|
const rows = readRows(inputPath);
|
||||||
const headerRowIndex = findHeaderRowIndex(rows);
|
const headerRowIndex = findHeaderRowIndex(rows);
|
||||||
const headers = rows[headerRowIndex] || [];
|
const headers = rows[headerRowIndex] || [];
|
||||||
@ -210,23 +246,12 @@ async function processCsvFile(jobId, inputPath, originalName) {
|
|||||||
outStream.write(['Distancia', 'Dedicado', 'Nao Dedicado', 'Erro', ...headers].join(';') + '\n');
|
outStream.write(['Distancia', 'Dedicado', 'Nao Dedicado', 'Erro', ...headers].join(';') + '\n');
|
||||||
|
|
||||||
for (const cols of rows.slice(headerRowIndex + 1)) {
|
for (const cols of rows.slice(headerRowIndex + 1)) {
|
||||||
let dataToSend = {};
|
const geoPayload = buildGeoPayload(cols, indexes);
|
||||||
|
const cepPayload = buildCepPayload(cols, indexes);
|
||||||
if (dataType === 'cep') {
|
if (!geoPayload && !cepPayload) continue;
|
||||||
dataToSend = buildCepPayload(cols, indexes);
|
|
||||||
if (!dataToSend) continue;
|
|
||||||
} else if (dataType === 'geolocalizacao') {
|
|
||||||
const latitude = indexes.idxLatitude >= 0 ? parseFloat(cols[indexes.idxLatitude]) : NaN;
|
|
||||||
const longitude = indexes.idxLongitude >= 0 ? parseFloat(cols[indexes.idxLongitude]) : NaN;
|
|
||||||
|
|
||||||
if (isNaN(latitude) || isNaN(longitude)) continue;
|
|
||||||
dataToSend = { latitude, longitude };
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const viab = await consultarViabilidade(dataToSend);
|
const viab = await consultarComFallback(geoPayload, cepPayload);
|
||||||
const distancia = viab.distancia ?? (viab.raw && (viab.raw.distancia || viab.raw.distance)) ?? '';
|
const distancia = viab.distancia ?? (viab.raw && (viab.raw.distancia || viab.raw.distance)) ?? '';
|
||||||
const dedicado = viab.dedicado ? 'Viavel' : 'Nao Viavel';
|
const dedicado = viab.dedicado ? 'Viavel' : 'Nao Viavel';
|
||||||
const naoDedicado = viab.naoDedicado ? 'Viavel' : 'Nao Viavel';
|
const naoDedicado = viab.naoDedicado ? 'Viavel' : 'Nao Viavel';
|
||||||
|
|||||||
@ -55,7 +55,7 @@ function findHeaderRow(rows) {
|
|||||||
return rows.find(row => {
|
return rows.find(row => {
|
||||||
const headers = row.map(normalizeHeader);
|
const headers = row.map(normalizeHeader);
|
||||||
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
||||||
const hasGeo = headers.includes('latitude') && headers.includes('longitude');
|
const hasGeo = hasGeoHeaders(headers);
|
||||||
return hasCepNumero || hasGeo;
|
return hasCepNumero || hasGeo;
|
||||||
}) || [];
|
}) || [];
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ async function readDelimitedHeaders(filePath) {
|
|||||||
if (!line.trim()) continue;
|
if (!line.trim()) continue;
|
||||||
const headers = line.split(detectDelimiter(line)).map(normalizeHeader);
|
const headers = line.split(detectDelimiter(line)).map(normalizeHeader);
|
||||||
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
||||||
const hasGeo = headers.includes('latitude') && headers.includes('longitude');
|
const hasGeo = hasGeoHeaders(headers);
|
||||||
if (hasCepNumero || hasGeo) {
|
if (hasCepNumero || hasGeo) {
|
||||||
rl.close();
|
rl.close();
|
||||||
return headers;
|
return headers;
|
||||||
@ -104,6 +104,11 @@ function hasAddressOrNumberHeader(headers) {
|
|||||||
|| header.includes('logradouro'));
|
|| header.includes('logradouro'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasGeoHeaders(headers) {
|
||||||
|
return headers.some(header => header.includes('latitude'))
|
||||||
|
&& headers.some(header => header.includes('longitude'));
|
||||||
|
}
|
||||||
|
|
||||||
async function consultarViabilidade(data) {
|
async function consultarViabilidade(data) {
|
||||||
try {
|
try {
|
||||||
const dataType = await discoverDataType(data);
|
const dataType = await discoverDataType(data);
|
||||||
@ -135,7 +140,7 @@ async function discoverDataType(input) {
|
|||||||
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
||||||
if (hasCepNumero) {
|
if (hasCepNumero) {
|
||||||
return 'cep';
|
return 'cep';
|
||||||
} else if (headers.includes('latitude') && headers.includes('longitude')) {
|
} else if (hasGeoHeaders(headers)) {
|
||||||
return 'geolocalizacao';
|
return 'geolocalizacao';
|
||||||
} else {
|
} else {
|
||||||
return 'unknown';
|
return 'unknown';
|
||||||
@ -144,7 +149,7 @@ async function discoverDataType(input) {
|
|||||||
// Trata como objeto de dados
|
// Trata como objeto de dados
|
||||||
if (input.cep && input.numero) {
|
if (input.cep && input.numero) {
|
||||||
return 'cep';
|
return 'cep';
|
||||||
} else if (input.latitude && input.longitude) {
|
} else if (input.latitude !== undefined && input.longitude !== undefined) {
|
||||||
return 'geolocalizacao';
|
return 'geolocalizacao';
|
||||||
} else {
|
} else {
|
||||||
return 'unknown';
|
return 'unknown';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user