From 011f7b8c4756f14ad6b070557311230de7e3b92f Mon Sep 17 00:00:00 2001 From: "gabriel.amancio" Date: Tue, 23 Jun 2026 15:30:29 -0300 Subject: [PATCH] =?UTF-8?q?REFAC:=20Refatora=C3=A7=C3=A3o=20da=20valida?= =?UTF-8?q?=C3=A7=C3=A3o=20de=20CSV=20para=20ampliar=20os=20padr=C3=B5es?= =?UTF-8?q?=20de=20planilhas=20de=20viabilidade.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/csvService.js | 26 +++++++++++++++++++++----- service/viabilidadeService.js | 4 ++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/service/csvService.js b/service/csvService.js index 28e15ac..6017e34 100644 --- a/service/csvService.js +++ b/service/csvService.js @@ -132,8 +132,9 @@ function hasAddressOrNumberHeader(headers) { } function hasGeoHeaders(headers) { - return hasHeaderAlias(headers, ['latitude', 'lat']) - && hasHeaderAlias(headers, ['longitude', 'long', 'lng', 'lon']); + const norm = headers.map(normalizeHeader); + return norm.some(h => /\blat(itude)?\b/.test(h)) + && norm.some(h => /\blo?n[g]?(itude)?\b/.test(h)); } function findHeaderRowIndex(rows) { @@ -152,8 +153,10 @@ 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', 'lat']), - idxLongitude: exactIndex(['longitude', 'long', 'lng', 'lon']) + // Antes: exactIndex(['latitude', 'lat']) + idxLatitude: findFirstHeaderIndex(headers, header => /\blat(itude)?\b/.test(header)), + // Antes: exactIndex(['longitude', 'long', 'lng', 'lon']) + idxLongitude: findFirstHeaderIndex(headers, header => /\blo?n[g]?(itude)?\b/.test(header)), }; } @@ -187,7 +190,20 @@ function buildCepPayload(cols, indexes) { } function parseCoordinate(value) { - const parsed = parseFloat(String(value ?? '').trim().replace(',', '.')); + const str = String(value ?? '') + .replace(/[\u00A0\u202F\u2000-\u200B\u3000]/g, '') // Bug 2: remove non-breaking spaces + .trim() + .replace(',', '.'); + + // Bug 3: converte DMS "17 38 18.80 S" → -17.638556 + const dms = str.match(/^(\d+)[°\s]+(\d+)['\s]+(\d+(?:\.\d+)?)["\s]*([NSEW])?$/i); + if (dms) { + const decimal = parseFloat(dms[1]) + parseFloat(dms[2]) / 60 + parseFloat(dms[3]) / 3600; + const negative = /[SW]/i.test(dms[4] ?? ''); + return negative ? -decimal : decimal; + } + + const parsed = parseFloat(str); return Number.isFinite(parsed) ? parsed : NaN; } diff --git a/service/viabilidadeService.js b/service/viabilidadeService.js index 8a14fe8..560b99b 100644 --- a/service/viabilidadeService.js +++ b/service/viabilidadeService.js @@ -105,8 +105,8 @@ function hasAddressOrNumberHeader(headers) { } function hasGeoHeaders(headers) { - return hasHeader(headers, ['latitude', 'lat']) - && hasHeader(headers, ['longitude', 'long', 'lng', 'lon']); + return headers.some(h => /\blat(itude)?\b/.test(h)) + && headers.some(h => /\blo?n[g]?(itude)?\b/.test(h)); } async function consultarViabilidade(data) { -- 2.43.0