diff --git a/front/next-env.d.ts b/front/next-env.d.ts index c4b7818..9edff1c 100644 --- a/front/next-env.d.ts +++ b/front/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/dev/types/routes.d.ts"; +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/functions/src/functions/scraping-functions.ts b/functions/src/functions/scraping-functions.ts index ef27e27..361993f 100644 --- a/functions/src/functions/scraping-functions.ts +++ b/functions/src/functions/scraping-functions.ts @@ -36,6 +36,8 @@ export async function scrapingsFunction( const responseCuencaSegura = await embalsesRepository.actualizarCuencaSegura(); + const responseCuencaMinoSil = await embalsesRepository.actualizarCuencaMinoSil(); + if (responseCuencaMediterranea) { context.log( "scrapings-function: Se han actualizado los embalses de la cuenca Mediterránea", @@ -92,6 +94,14 @@ export async function scrapingsFunction( ); } + if (responseCuencaMinoSil) { + context.log(`Se han actualizado los embalses de la cuenca Mino Sil`); + } else { + context.log( + "No se han podido actualizar los embalses de la cuenca Mino Sil" + ); + } + } catch (error) { context.error("scrapings-function: ERROR", error); throw error; diff --git a/integrations/scraping-cuenca-mino-sil/package.json b/integrations/scraping-cuenca-mino-sil/package.json index c728ec0..fbfb846 100644 --- a/integrations/scraping-cuenca-mino-sil/package.json +++ b/integrations/scraping-cuenca-mino-sil/package.json @@ -4,12 +4,20 @@ "private": true, "type": "module", "exports": { - ".": "./src/index.ts" + ".": "./dist/index.js" }, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", "scripts": { - "start": "tsx --watch src/console-runner.ts" + "start": "tsx --watch src/console-runner.ts", + "build": "run-p clean type-check build:scraping-cuenca-mino-sil", + "build:scraping-cuenca-mino-sil": "tsc", + "clean": "rimraf dist", + "type-check": "tsc --noEmit --preserveWatchOutput" }, "dependencies": { + "axios": "^1.7.0", + "cheerio": "^1.1.2", "db-model": "^1.0.0" } } diff --git a/integrations/scraping-cuenca-mino-sil/src/api/cuenca.api.ts b/integrations/scraping-cuenca-mino-sil/src/api/cuenca.api.ts new file mode 100644 index 0000000..2f26280 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/api/cuenca.api.ts @@ -0,0 +1,47 @@ +import axios from "axios"; +import https from "https"; + +const httpsAgent = new https.Agent({ + rejectUnauthorized: false, +}); + +const browserHeaders = { + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", + Accept: + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Language": "es-ES,es;q=0.9,en;q=0.8", +}; + +const BASE_URL = + "https://saih.chminosil.es/index.php?url=/datos/mapas/mapa:H1/area:HID/acc:1"; +const TARGET_URL = + "https://saih.chminosil.es/index.php?url=/datos/situacionEmbalses"; + +export async function getCuencaPageHTMLContent(): Promise { + const sessionResponse = await axios.get(BASE_URL, { + httpsAgent, + maxRedirects: 0, + headers: browserHeaders, + validateStatus: (status) => status >= 200 && status < 400, + }); + + const setCookieHeaders = sessionResponse.headers["set-cookie"]; + const cookieString = setCookieHeaders + ? setCookieHeaders + .map((cookie: string) => cookie.split(";")[0]) + .join("; ") + : ""; + + const { data: html } = await axios.get(TARGET_URL, { + httpsAgent, + maxRedirects: 10, + headers: { + ...browserHeaders, + Cookie: cookieString, + Referer: BASE_URL, + }, + }); + + return html; +} diff --git a/integrations/scraping-cuenca-mino-sil/src/api/cuenca.model.ts b/integrations/scraping-cuenca-mino-sil/src/api/cuenca.model.ts new file mode 100644 index 0000000..1489d40 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/api/cuenca.model.ts @@ -0,0 +1,7 @@ +export interface EmbalsesMinoSil { + id: number; + embalse: string; + capacidadTotalHm3: number; + volumenActualHm3: number; + fecha: string; +} diff --git a/integrations/scraping-cuenca-mino-sil/src/api/index.ts b/integrations/scraping-cuenca-mino-sil/src/api/index.ts new file mode 100644 index 0000000..b9296d5 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/api/index.ts @@ -0,0 +1,2 @@ +export * from "./cuenca.api.js"; +export * from "./cuenca.model.js"; diff --git a/integrations/scraping-cuenca-mino-sil/src/console-runner.ts b/integrations/scraping-cuenca-mino-sil/src/console-runner.ts index d88d339..f4284ce 100644 --- a/integrations/scraping-cuenca-mino-sil/src/console-runner.ts +++ b/integrations/scraping-cuenca-mino-sil/src/console-runner.ts @@ -1,5 +1,5 @@ -import { getEstadoCuencaMinoSil } from "./integration"; +import { scrapeCuencaMinioSil } from "./integration.js"; console.log("Estado de la Cuenca Miño Sil:"); -const result = await getEstadoCuencaMinoSil(); -console.log(JSON.stringify(result, null, 2)); +const result = await scrapeCuencaMinioSil(); +console.log(result); diff --git a/integrations/scraping-cuenca-mino-sil/src/index.ts b/integrations/scraping-cuenca-mino-sil/src/index.ts index 992c96b..25e269a 100644 --- a/integrations/scraping-cuenca-mino-sil/src/index.ts +++ b/integrations/scraping-cuenca-mino-sil/src/index.ts @@ -1,2 +1,2 @@ -export * from "./integration"; +export * from "./integration.js"; diff --git a/integrations/scraping-cuenca-mino-sil/src/integration.ts b/integrations/scraping-cuenca-mino-sil/src/integration.ts index 783ff90..d997214 100644 --- a/integrations/scraping-cuenca-mino-sil/src/integration.ts +++ b/integrations/scraping-cuenca-mino-sil/src/integration.ts @@ -1,24 +1,13 @@ -import type { Embalse } from "db-model"; +import * as cheerio from "cheerio"; +import { EmbalseUpdateSAIHEntity } from "db-model"; +import { getCuencaPageHTMLContent } from "./api/index.js"; +import { extractProvinceTables } from "./scraper/index.js"; +import { mapToEmbalseUpdateSAIH } from './scraper/index.js'; -export const getEstadoCuencaMinoSil = async (): Promise => { - return [ - { - id: "1", - nombre: "Embalse de Belesar", - provincia: "Lugo", - capacidad: 3000000000, - nivelActual: 2500000000, - fechaUltimoNivel: new Date("2023-10-01"), - porcentajeLlenado: 83.3, - }, - { - id: "2", - nombre: "Embalse de Velle", - provincia: "Ourense", - capacidad: 500000000, - nivelActual: 400000000, - fechaUltimoNivel: new Date("2023-10-01"), - porcentajeLlenado: 80.0, - }, - ]; -}; +export async function scrapeCuencaMinioSil(): Promise { + const html = await getCuencaPageHTMLContent(); + const $: cheerio.CheerioAPI = cheerio.load(html); + const rawEmbalses = extractProvinceTables($); + + return mapToEmbalseUpdateSAIH(rawEmbalses); +} diff --git a/integrations/scraping-cuenca-mino-sil/src/scraper/business.ts b/integrations/scraping-cuenca-mino-sil/src/scraper/business.ts new file mode 100644 index 0000000..135ddc9 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/scraper/business.ts @@ -0,0 +1,44 @@ +import * as cheerio from "cheerio"; +import { EmbalsesMinoSil } from '../api/index.js'; +import { mapStringToApiDate } from './helpers.js'; + +export function parseEuropeanNumber(value: string): number { + if (!value || value.trim() === "" || value === "*" || value === "n/d") { + return NaN; + } + + // Replace comma with dot for decimal separator + const normalizedValue = value.replace(",", "."); + return parseFloat(normalizedValue); +} + +export function extractProvinceTables( + $: cheerio.CheerioAPI +): EmbalsesMinoSil[] { + + let embalses: EmbalsesMinoSil[] = []; + + $("table.tabla tr").each((_index, row) => { + const cells = $(row).find("td"); + if (cells.length === 0) return; // Skip header rows with + + const nombre = $(cells[1]).text().trim(); + if (!nombre || !nombre.includes(" - ")) return; // Skip totals row + const id = nombre.split(" - ")[0].trim().match(/^([A-Z])(\d+)$/)[2]; // Extract ID from name + const capacidadTotal = $(cells[4]).text().trim(); + const fecha = $(cells[8]).text().trim(); + const volumenActual = $(cells[6]).text().trim(); + + const embalse: EmbalsesMinoSil = { + id: Number(id), + embalse: nombre.split(" - ")[1].trim(), + capacidadTotalHm3: parseEuropeanNumber(capacidadTotal), + volumenActualHm3: parseEuropeanNumber(volumenActual), + fecha: mapStringToApiDate(fecha) + }; + + embalses = [...embalses, embalse]; + }); + + return embalses; +} diff --git a/integrations/scraping-cuenca-mino-sil/src/scraper/helpers.ts b/integrations/scraping-cuenca-mino-sil/src/scraper/helpers.ts new file mode 100644 index 0000000..206b950 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/scraper/helpers.ts @@ -0,0 +1,5 @@ +export const mapStringToApiDate = (strDate: string) => { + const [day, month, year] = strDate.split(" ")[0].split('/'); + + return `${day}/${month}/${year}`; +} diff --git a/integrations/scraping-cuenca-mino-sil/src/scraper/index.ts b/integrations/scraping-cuenca-mino-sil/src/scraper/index.ts new file mode 100644 index 0000000..a6e3484 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/scraper/index.ts @@ -0,0 +1,3 @@ +export * from './business.js'; +export * from './helpers.js'; +export * from './mapper.js'; diff --git a/integrations/scraping-cuenca-mino-sil/src/scraper/mapper.ts b/integrations/scraping-cuenca-mino-sil/src/scraper/mapper.ts new file mode 100644 index 0000000..52ce291 --- /dev/null +++ b/integrations/scraping-cuenca-mino-sil/src/scraper/mapper.ts @@ -0,0 +1,13 @@ +import { EmbalseUpdateSAIHEntity } from 'db-model'; +import { EmbalsesMinoSil } from '../api/index.js'; + +export function mapToEmbalseUpdateSAIH( + embalsesMinoSil: EmbalsesMinoSil[] +): EmbalseUpdateSAIHEntity[] { + return embalsesMinoSil.map((embalse) => ({ + id: embalse.id, + nombre: embalse.embalse, + aguaActualSAIH: embalse.volumenActualHm3, + fechaMedidaSAIH: embalse.fecha, + })); +} diff --git a/integrations/scraping-cuenca-mino-sil/tsconfig.json b/integrations/scraping-cuenca-mino-sil/tsconfig.json index 5b80506..ce7b1d4 100644 --- a/integrations/scraping-cuenca-mino-sil/tsconfig.json +++ b/integrations/scraping-cuenca-mino-sil/tsconfig.json @@ -1,11 +1,16 @@ { "compilerOptions": { "target": "ESNext", - "module": "ESNext", - "moduleResolution": "bundler", + "module": "nodenext", + "moduleResolution": "nodenext", + "outDir": "dist", "skipLibCheck": true, "isolatedModules": true, - "esModuleInterop": true + "esModuleInterop": true, + "verbatimModuleSyntax": false, + "declaration": true, + "baseUrl": "./" }, - "include": ["src"] + "include": ["src/**/*"], + "exclude": ["dist", "node_modules"] } diff --git a/package-lock.json b/package-lock.json index f9098a3..b34d59a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -173,6 +173,8 @@ "integrations/scraping-cuenca-mino-sil": { "version": "1.0.0", "dependencies": { + "axios": "^1.7.0", + "cheerio": "^1.1.2", "db-model": "^1.0.0" } }, @@ -1413,6 +1415,7 @@ "version": "24.3.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.10.0" } @@ -1435,6 +1438,7 @@ "version": "19.1.10", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2172,6 +2176,7 @@ "node_modules/d3-selection": { "version": "3.0.0", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -3660,6 +3665,7 @@ "version": "3.7.3", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -3810,6 +3816,7 @@ "node_modules/react": { "version": "19.1.1", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3817,6 +3824,7 @@ "node_modules/react-dom": { "version": "19.1.1", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -4539,6 +4547,7 @@ "version": "5.9.2", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4568,6 +4577,7 @@ "version": "7.1.3", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -4916,6 +4926,111 @@ }, "packages/db-model": { "version": "1.0.0" + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz", + "integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz", + "integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz", + "integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz", + "integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz", + "integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz", + "integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz", + "integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/packages/db/package.json b/packages/db/package.json index c103c88..011af4b 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -30,7 +30,8 @@ "scraping-cuenca-duero": "*", "scraping-cuenca-jucar": "*", "scraping-cuenca-mediterranea": "*", - "scraping-cuenca-segura": "*" + "scraping-cuenca-segura": "*", + "scraping-cuenca-mino-sil": "*" }, "devDependencies": { "@types/prompts": "^2.4.9", diff --git a/packages/db/src/dals/embalses/embalses.helpers.ts b/packages/db/src/dals/embalses/embalses.helpers.ts index b6e1d88..5b5a842 100644 --- a/packages/db/src/dals/embalses/embalses.helpers.ts +++ b/packages/db/src/dals/embalses/embalses.helpers.ts @@ -1,4 +1,5 @@ export const parseDate = (dateStr: string): Date => { const [day, month, year] = dateStr.split("/").map(Number); - return new Date(year, month - 1, day); + // Crea la fecha en UTC para evitar desfase por zona horaria + return new Date(Date.UTC(year, month - 1, day)); }; diff --git a/packages/db/src/dals/embalses/embalses.mappers.ts b/packages/db/src/dals/embalses/embalses.mappers.ts index 7035d10..7992ff4 100644 --- a/packages/db/src/dals/embalses/embalses.mappers.ts +++ b/packages/db/src/dals/embalses/embalses.mappers.ts @@ -214,3 +214,39 @@ export const mapperFromCuencasSeguraToArcgis = new Map< [4, { nombre: "Camarillas", idArcgis: 72 }], [5, { nombre: "La Pedrera", idArcgis: 180 }], ]); + +// Ojo AZUFRE, MONTEARENAS, GUISTOLAS + +export const mapperFromCuencasMinoSilToArcgis = new Map< + number, + InfoDestinoArcgis +>([ + [3, { nombre: "LAS ROZA", idArcgis: 262 }], + [5, { nombre: "MATALAVILLA", idArcgis: 198 }], + [7, { nombre: "BÁRCENA", idArcgis: 67 }], + [1, { nombre: "BELESAR", idArcgis: 45 }], + [2, { nombre: "OS PEARES", idArcgis: 221 }], + [13, { nombre: "SAN MARTIÑO", idArcgis: 278 }], + [23, { nombre: "MONTEFURADO", idArcgis: 205 }], + [27, { nombre: "SANTO ESTEVO", idArcgis: 275 }], + [28, { nombre: "VILASOUTO", idArcgis: 339 }], + [16, { nombre: "AS PORTAS", idArcgis: 234 }], + [18, { nombre: "BAO", idArcgis: 37 }], + [19, { nombre: "PRADA", idArcgis: 238 }], + [30, { nombre: "VELLE", idArcgis: 335 }], + [31, { nombre: "CASTRELO", idArcgis: 85 }], + [32, { nombre: "ALBARELLOS", idArcgis: 10 }], + [33, { nombre: "FRIEIRA", idArcgis: 142 }], + [35, { nombre: "AS CONCHAS", idArcgis: 107 }], + [36, { nombre: "SALAS", idArcgis: 269 }], + [39, { nombre: "LA CAMPAÑANA", idArcgis: 73 }], + [40, { nombre: "PEÑARRUBIA", idArcgis: 226 }], + [66, { nombre: "SEQUEIROS", idArcgis: 292 }], + [70, { nombre: "SAN PEDRO", idArcgis: 279 }], + [74, { nombre: "SAN SEBASTIÁN", idArcgis: 281 }], + [76, { nombre: "PÍAS", idArcgis: 246 }], + [77, { nombre: "CENZA", idArcgis: 95 }], + [82, { nombre: "SANTA EULALIA", idArcgis: 285 }], + [89, { nombre: "CHANDREXA", idArcgis: 99 }], + [97, { nombre: "EDRADA", idArcgis: 124 }], +]) diff --git a/packages/db/src/dals/embalses/embalses.repository.ts b/packages/db/src/dals/embalses/embalses.repository.ts index 0ef4a23..02edb89 100644 --- a/packages/db/src/dals/embalses/embalses.repository.ts +++ b/packages/db/src/dals/embalses/embalses.repository.ts @@ -1,6 +1,6 @@ import { scrapeSeedEmbalses } from "arcgis"; import { getEmbalsesContext } from "./embalses.context.js"; -import { mapperFromCuencasMediterraneaToArcgis, mapperFromCuencasCantabricoToArcgis, mapperFromCuencasCatalanaToArcgis, mapperFromCuencasDueroToArcgis, mapperFromCuencasJucarToArcgis, mapperFromCuencasSeguraToArcgis } from "./embalses.mappers.js"; +import { mapperFromCuencasMediterraneaToArcgis, mapperFromCuencasCantabricoToArcgis, mapperFromCuencasCatalanaToArcgis, mapperFromCuencasDueroToArcgis, mapperFromCuencasJucarToArcgis, mapperFromCuencasSeguraToArcgis, mapperFromCuencasMinoSilToArcgis } from "./embalses.mappers.js"; import { scrapeCuencaMediterranea } from "scraping-cuenca-mediterranea"; import { scrapeCuencaCantabrica } from 'scraping-cuenca-cantabrico'; import { integracionCuencaCatalana } from 'scraping-cuenca-catalana'; @@ -10,6 +10,7 @@ import { getEstadoCuencaDuero } from 'scraping-cuenca-duero'; // import { scrapeCuencaGuadalquivir } from 'scraping-cuenca-guadalquivir'; import { scrapeCuencaJucar } from 'scraping-cuenca-jucar'; import { scrapeCuencaSegura } from 'scraping-cuenca-segura'; +import { scrapeCuencaMinioSil } from 'scraping-cuenca-mino-sil'; import { parseDate } from "./embalses.helpers.js"; export const embalsesRepository = { @@ -340,6 +341,55 @@ export const embalsesRepository = { } } + return actualizados > 0; + }, + actualizarCuencaMinoSil: async (): Promise => { + const embalsesMinoSil = await scrapeCuencaMinioSil(); + + console.log( + `Se han scrapeado ${embalsesMinoSil.length} embalses de la Cuenca Mino Sil` + ); + + let actualizados = 0; + let noEncontrados = 0; + let sinMapper = 0; + + for (const embalse of embalsesMinoSil) { + const infoDestino = mapperFromCuencasMinoSilToArcgis.get(embalse.id); + + if (!infoDestino) { + sinMapper++; + console.warn(`Sin mapper para ID ${embalse.id} - ${embalse.nombre}`); + continue; + } + + console.log( + `🔍 Mapeando: ID scraping ${embalse.id} -> _id BD ${infoDestino.idArcgis} (${infoDestino.nombre})` + ); + + const { matchedCount } = await getEmbalsesContext().updateOne( + { _id: infoDestino.idArcgis.toString() }, + { + $set: { + aguaActualSAIH: embalse.aguaActualSAIH, + fechaMedidaAguaActualSAIH: parseDate(embalse.fechaMedidaSAIH), + }, + } + ); + + if (matchedCount > 0) { + actualizados++; + console.log( + `Actualizado: ${infoDestino.nombre} (_id: ${infoDestino.idArcgis}) -> ${embalse.aguaActualSAIH} hm³` + ); + } else { + noEncontrados++; + console.warn( + `No encontrado en BD: _id ${infoDestino.idArcgis} - ${infoDestino.nombre}` + ); + } + } + return actualizados > 0; } };