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) {
|
||||
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) {
|
||||
@ -136,8 +137,8 @@ function resolveColumnIndexes(headers) {
|
||||
idxCep: findFirstHeaderIndex(headers, header => /\bcep\b/.test(header) || header === 'codigo postal'),
|
||||
idxNumero: exactIndex(['numero', 'número', 'num', 'nº', 'n°']),
|
||||
idxEndereco: findFirstHeaderIndex(headers, header => header.includes('endereco') || header.includes('logradouro')),
|
||||
idxLatitude: exactIndex(['latitude']),
|
||||
idxLongitude: exactIndex(['longitude'])
|
||||
idxLatitude: findFirstHeaderIndex(headers, header => header.includes('latitude')),
|
||||
idxLongitude: findFirstHeaderIndex(headers, header => header.includes('longitude'))
|
||||
};
|
||||
}
|
||||
|
||||
@ -170,13 +171,52 @@ function buildCepPayload(cols, indexes) {
|
||||
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) {
|
||||
const text = String(value ?? '').replace(/[\r\n;]/g, ' ');
|
||||
return text.includes('"') ? text.replace(/"/g, "'") : text;
|
||||
}
|
||||
|
||||
async function countValidLines(inputPath) {
|
||||
const dataType = await discoverDataType(inputPath);
|
||||
await discoverDataType(inputPath);
|
||||
const rows = readRows(inputPath);
|
||||
const headerRowIndex = findHeaderRowIndex(rows);
|
||||
const headers = rows[headerRowIndex] || [];
|
||||
@ -184,20 +224,16 @@ async function countValidLines(inputPath) {
|
||||
let total = 0;
|
||||
|
||||
for (const cols of rows.slice(headerRowIndex + 1)) {
|
||||
if (dataType === 'cep') {
|
||||
if (buildCepPayload(cols, indexes)) total++;
|
||||
} 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)) total++;
|
||||
}
|
||||
const geoPayload = buildGeoPayload(cols, indexes);
|
||||
const cepPayload = buildCepPayload(cols, indexes);
|
||||
if (geoPayload || cepPayload) total++;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
async function processCsvFile(jobId, inputPath, originalName) {
|
||||
const dataType = await discoverDataType(inputPath);
|
||||
await discoverDataType(inputPath);
|
||||
const rows = readRows(inputPath);
|
||||
const headerRowIndex = findHeaderRowIndex(rows);
|
||||
const headers = rows[headerRowIndex] || [];
|
||||
@ -210,23 +246,12 @@ async function processCsvFile(jobId, inputPath, originalName) {
|
||||
outStream.write(['Distancia', 'Dedicado', 'Nao Dedicado', 'Erro', ...headers].join(';') + '\n');
|
||||
|
||||
for (const cols of rows.slice(headerRowIndex + 1)) {
|
||||
let dataToSend = {};
|
||||
|
||||
if (dataType === 'cep') {
|
||||
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;
|
||||
}
|
||||
const geoPayload = buildGeoPayload(cols, indexes);
|
||||
const cepPayload = buildCepPayload(cols, indexes);
|
||||
if (!geoPayload && !cepPayload) continue;
|
||||
|
||||
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 dedicado = viab.dedicado ? 'Viavel' : 'Nao Viavel';
|
||||
const naoDedicado = viab.naoDedicado ? 'Viavel' : 'Nao Viavel';
|
||||
|
||||
@ -55,7 +55,7 @@ function findHeaderRow(rows) {
|
||||
return rows.find(row => {
|
||||
const headers = row.map(normalizeHeader);
|
||||
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
||||
const hasGeo = headers.includes('latitude') && headers.includes('longitude');
|
||||
const hasGeo = hasGeoHeaders(headers);
|
||||
return hasCepNumero || hasGeo;
|
||||
}) || [];
|
||||
}
|
||||
@ -83,7 +83,7 @@ async function readDelimitedHeaders(filePath) {
|
||||
if (!line.trim()) continue;
|
||||
const headers = line.split(detectDelimiter(line)).map(normalizeHeader);
|
||||
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
||||
const hasGeo = headers.includes('latitude') && headers.includes('longitude');
|
||||
const hasGeo = hasGeoHeaders(headers);
|
||||
if (hasCepNumero || hasGeo) {
|
||||
rl.close();
|
||||
return headers;
|
||||
@ -104,6 +104,11 @@ function hasAddressOrNumberHeader(headers) {
|
||||
|| header.includes('logradouro'));
|
||||
}
|
||||
|
||||
function hasGeoHeaders(headers) {
|
||||
return headers.some(header => header.includes('latitude'))
|
||||
&& headers.some(header => header.includes('longitude'));
|
||||
}
|
||||
|
||||
async function consultarViabilidade(data) {
|
||||
try {
|
||||
const dataType = await discoverDataType(data);
|
||||
@ -135,7 +140,7 @@ async function discoverDataType(input) {
|
||||
const hasCepNumero = hasCepHeader(headers) && hasAddressOrNumberHeader(headers);
|
||||
if (hasCepNumero) {
|
||||
return 'cep';
|
||||
} else if (headers.includes('latitude') && headers.includes('longitude')) {
|
||||
} else if (hasGeoHeaders(headers)) {
|
||||
return 'geolocalizacao';
|
||||
} else {
|
||||
return 'unknown';
|
||||
@ -144,7 +149,7 @@ async function discoverDataType(input) {
|
||||
// Trata como objeto de dados
|
||||
if (input.cep && input.numero) {
|
||||
return 'cep';
|
||||
} else if (input.latitude && input.longitude) {
|
||||
} else if (input.latitude !== undefined && input.longitude !== undefined) {
|
||||
return 'geolocalizacao';
|
||||
} else {
|
||||
return 'unknown';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user