Rafael Lopez

descagras

...@@ -102,14 +102,7 @@ ...@@ -102,14 +102,7 @@
102 codigo = String(meta.municipio_ubigeo || ''); 102 codigo = String(meta.municipio_ubigeo || '');
103 tipo = 'ubigeo'; 103 tipo = 'ubigeo';
104 } else if (isClass && cls === 'acteco') { 104 } else if (isClass && cls === 'acteco') {
105 - const s = meta.acteco_sector != null ? String(Math.round(meta.acteco_sector)) : ''; 105 + codigo = meta.acteco_actividad_armonizado || meta.acteco_subsector_armonizado || meta.acteco_sector_armonizado || '';
106 - if (s) {
107 - codigo = s;
108 - if (meta.acteco_subsector != null) {
109 - codigo += '.' + Math.round(meta.acteco_subsector);
110 - if (meta.acteco_actividad != null) codigo += '.' + Math.round(meta.acteco_actividad);
111 - }
112 - }
113 tipo = 'acteco'; 106 tipo = 'acteco';
114 } else if (!isClass) { 107 } else if (!isClass) {
115 // Programa/proyecto 108 // Programa/proyecto
......
...@@ -796,10 +796,7 @@ ...@@ -796,10 +796,7 @@
796 } else if (isFinfunClass) { 796 } else if (isFinfunClass) {
797 url = `/finfun/${getFinfunCodigo(meta)}`; 797 url = `/finfun/${getFinfunCodigo(meta)}`;
798 } else if (hit.document.class_ === 'acteco') { 798 } else if (hit.document.class_ === 'acteco') {
799 - const s = String(meta.acteco_sector ? Math.round(meta.acteco_sector) : ''); 799 + const code = meta.acteco_actividad_armonizado || meta.acteco_subsector_armonizado || meta.acteco_sector_armonizado || '';
800 - let code = s;
801 - if (meta.acteco_actividad !== undefined && meta.acteco_subsector !== undefined) code = `${s}.${Math.round(meta.acteco_subsector)}.${Math.round(meta.acteco_actividad)}`;
802 - else if (meta.acteco_subsector !== undefined) code = `${s}.${Math.round(meta.acteco_subsector)}`;
803 url = `/acteco/${code}`; 800 url = `/acteco/${code}`;
804 } else if (hit.document.class_ === 'rubro') { 801 } else if (hit.document.class_ === 'rubro') {
805 const code = meta.rubro_sub_cuenta || meta.rubro_cuenta || meta.rubro_clase || meta.rubro_tipo || ''; 802 const code = meta.rubro_sub_cuenta || meta.rubro_cuenta || meta.rubro_clase || meta.rubro_tipo || '';
...@@ -1438,7 +1435,7 @@ ...@@ -1438,7 +1435,7 @@
1438 {@const isOrganismoClass = hit.document.class_ === 'organismo'} 1435 {@const isOrganismoClass = hit.document.class_ === 'organismo'}
1439 {@const isClassResult = hit.document.is_class === true} 1436 {@const isClassResult = hit.document.is_class === true}
1440 {@const hitType = CLASS_REVERSE_MAP[hit.document.class_] || hit.document.class_} 1437 {@const hitType = CLASS_REVERSE_MAP[hit.document.class_] || hit.document.class_}
1441 - {@const actecoCode = isActecoClass ? (() => { const s = String(meta.acteco_sector ? Math.round(meta.acteco_sector) : ''); if (meta.acteco_actividad !== undefined && meta.acteco_subsector !== undefined) return `${s}.${Math.round(meta.acteco_subsector)}.${Math.round(meta.acteco_actividad)}`; if (meta.acteco_subsector !== undefined) return `${s}.${Math.round(meta.acteco_subsector)}`; return s; })() : ''} 1438 + {@const actecoCode = isActecoClass ? (meta.acteco_actividad_armonizado || meta.acteco_subsector_armonizado || meta.acteco_sector_armonizado || '') : ''}
1442 {@const rubroCode = isRubroClass ? (meta.rubro_sub_cuenta || meta.rubro_cuenta || meta.rubro_clase || meta.rubro_tipo || '') : ''} 1439 {@const rubroCode = isRubroClass ? (meta.rubro_sub_cuenta || meta.rubro_cuenta || meta.rubro_clase || meta.rubro_tipo || '') : ''}
1443 <a 1440 <a
1444 href={isEntidadClass 1441 href={isEntidadClass
......
...@@ -42,15 +42,8 @@ ...@@ -42,15 +42,8 @@
42 const doc = hit.document || {}; 42 const doc = hit.document || {};
43 let meta = {}; 43 let meta = {};
44 try { meta = typeof doc.metadatos === 'string' ? JSON.parse(doc.metadatos) : (doc.metadatos || {}); } catch {} 44 try { meta = typeof doc.metadatos === 'string' ? JSON.parse(doc.metadatos) : (doc.metadatos || {}); } catch {}
45 - const s = meta.acteco_sector != null ? String(Math.round(meta.acteco_sector)) : ''; 45 + const code = meta.acteco_actividad_armonizado || meta.acteco_subsector_armonizado || meta.acteco_sector_armonizado || '';
46 - if (!s) return null; 46 + if (!code) return null;
47 - let code = s;
48 - if (meta.acteco_subsector != null) {
49 - code += '.' + Math.round(meta.acteco_subsector);
50 - if (meta.acteco_actividad != null) {
51 - code += '.' + Math.round(meta.acteco_actividad);
52 - }
53 - }
54 return { code, label: doc.texto || '' }; 47 return { code, label: doc.texto || '' };
55 }).filter(Boolean); 48 }).filter(Boolean);
56 } catch { 49 } catch {
......
1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/ubigeo/todo';
3 +
4 +export async function GET({ url }) {
5 + const gestion = url.searchParams.get('gestion') || '';
6 +
7 + const apiUrl = new URL(API_BASE);
8 + if (gestion) apiUrl.searchParams.set('gestion', gestion);
9 +
10 + try {
11 + const response = await fetch(apiUrl.toString());
12 + if (!response.ok) {
13 + return new Response(JSON.stringify({ error: `API error: ${response.status}` }), {
14 + status: response.status, headers: { 'Content-Type': 'application/json' }
15 + });
16 + }
17 + const data = await response.json();
18 + return new Response(JSON.stringify(data), {
19 + headers: { 'Content-Type': 'application/json' }
20 + });
21 + } catch {
22 + return new Response(JSON.stringify({ error: 'Failed to fetch' }), {
23 + status: 500, headers: { 'Content-Type': 'application/json' }
24 + });
25 + }
26 +}
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
96 <!-- Completo --> 96 <!-- Completo -->
97 <div class="section"> 97 <div class="section">
98 <h2 class="section-title">Completo</h2> 98 <h2 class="section-title">Completo</h2>
99 - <a href={buildUrl('completo', 'ultimo')} class="download-link"> 99 + <a href={buildUrl('completo', 'ultimo')} download rel="external" class="download-link">
100 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg> 100 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
101 Descargar todo ({dataset === 'gasto' ? 'gastos' : 'ingresos'}) 101 Descargar todo ({dataset === 'gasto' ? 'gastos' : 'ingresos'})
102 </a> 102 </a>
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
107 <h2 class="section-title">Por gestión</h2> 107 <h2 class="section-title">Por gestión</h2>
108 <div class="year-grid"> 108 <div class="year-grid">
109 {#each YEARS as year} 109 {#each YEARS as year}
110 - <a href={buildUrl('gestion', year)} class="year-link">{year}</a> 110 + <a href={buildUrl('gestion', year)} download rel="external" class="year-link">{year}</a>
111 {/each} 111 {/each}
112 </div> 112 </div>
113 </div> 113 </div>
...@@ -155,7 +155,7 @@ ...@@ -155,7 +155,7 @@
155 {#if selectedEntity} 155 {#if selectedEntity}
156 <div class="entity-result"> 156 <div class="entity-result">
157 <span class="entity-name">{selectedEntity.desc_entidad}</span> 157 <span class="entity-name">{selectedEntity.desc_entidad}</span>
158 - <a href={buildUrl('entidad', selectedEntity.entidad)} class="download-link"> 158 + <a href={buildUrl('entidad', selectedEntity.entidad)} download rel="external" class="download-link">
159 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg> 159 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
160 Descargar 160 Descargar
161 </a> 161 </a>
......
1 export const ssr = false; 1 export const ssr = false;
2 2
3 export async function load({ fetch }) { 3 export async function load({ fetch }) {
4 - const pobRes = await fetch('/poblacion.csv').then(r => r.text()); 4 + const [pobRes, ubigeoRes] = await Promise.all([
5 + fetch('/poblacion.csv').then(r => r.text()),
6 + fetch('/api/ubigeo-todo?gestion=2025').then(r => r.json())
7 + ]);
5 8
6 const poblacionMap = {}; 9 const poblacionMap = {};
7 pobRes.split('\n').slice(1).forEach(line => { 10 pobRes.split('\n').slice(1).forEach(line => {
...@@ -11,10 +14,22 @@ export async function load({ fetch }) { ...@@ -11,10 +14,22 @@ export async function load({ fetch }) {
11 } 14 }
12 }); 15 });
13 16
17 + const resumen = (ubigeoRes || [])
18 + .filter(d => d.ubigeo !== '0.0.0' && !d.ubigeo.endsWith('.0') && !/multimunicipal/i.test(d.desc_ubigeo) && !/multiprovincial/i.test(d.desc_ubigeo) && !/desconocido/i.test(d.desc_ubigeo))
19 + .map(d => ({
20 + codigo: d.ubigeo,
21 + desc: d.desc_ubigeo,
22 + gestion: d.gestion,
23 + devengado: d.monto,
24 + ranking: d.ranking,
25 + per_capita: d.per_capita,
26 + departamento: d.desc_departamento
27 + }));
28 +
14 const gestiones = [2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025]; 29 const gestiones = [2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025];
15 30
16 return { 31 return {
17 - resumen: [], 32 + resumen,
18 poblacionMap, 33 poblacionMap,
19 gestiones, 34 gestiones,
20 gestionInicial: 2025 35 gestionInicial: 2025
......
...@@ -66,10 +66,7 @@ ...@@ -66,10 +66,7 @@
66 return fin; 66 return fin;
67 }}, 67 }},
68 acteco: { class_: 'acteco', codigoFn: (meta) => { 68 acteco: { class_: 'acteco', codigoFn: (meta) => {
69 - const s = String(meta.acteco_sector ? Math.round(meta.acteco_sector) : ''); 69 + return meta.acteco_actividad_armonizado || meta.acteco_subsector_armonizado || meta.acteco_sector_armonizado || '';
70 - if (meta.acteco_actividad !== undefined) return `${s}.${Math.round(meta.acteco_subsector)}.${Math.round(meta.acteco_actividad)}`;
71 - if (meta.acteco_subsector !== undefined) return `${s}.${Math.round(meta.acteco_subsector)}`;
72 - return s;
73 }}, 70 }},
74 }; 71 };
75 72
...@@ -204,12 +201,7 @@ ...@@ -204,12 +201,7 @@
204 const map = {}; 201 const map = {};
205 const esClasificador = clasificadorSeleccionado !== 'total' && clasSeleccionado; 202 const esClasificador = clasificadorSeleccionado !== 'total' && clasSeleccionado;
206 resumen.forEach(d => { 203 resumen.forEach(d => {
207 - let val; 204 + const val = modoPerCapita ? (d.per_capita || 0) : d.devengado;
208 - if (modoPerCapita) {
209 - val = esClasificador ? (d.per_capita || 0) : (poblacionMap[d.codigo] ? d.devengado / poblacionMap[d.codigo] : d.devengado);
210 - } else {
211 - val = d.devengado;
212 - }
213 map[d.codigo] = { ...d, valor: val }; 205 map[d.codigo] = { ...d, valor: val };
214 }); 206 });
215 return map; 207 return map;
...@@ -378,9 +370,31 @@ ...@@ -378,9 +370,31 @@
378 return; 370 return;
379 } 371 }
380 372
381 - // Modo total: datos no disponibles sin Supabase 373 + // Modo total: cargar gasto agregado por municipio
382 - // TODO: implementar endpoint API para resumen por municipio 374 + const key = `total_${gestion}`;
375 + if (resumenCache[key]) {
376 + resumen = resumenCache[key];
377 + } else {
378 + try {
379 + const res = await fetch(`/api/ubigeo-todo?gestion=${gestion}`);
380 + const data = await res.json();
381 + const mapped = (data || [])
382 + .filter(d => d.ubigeo !== '0.0.0' && !d.ubigeo.endsWith('.0') && !/multimunicipal/i.test(d.desc_ubigeo) && !/multiprovincial/i.test(d.desc_ubigeo) && !/desconocido/i.test(d.desc_ubigeo))
383 + .map(d => ({
384 + codigo: d.ubigeo,
385 + desc: d.desc_ubigeo,
386 + gestion: d.gestion,
387 + devengado: d.monto,
388 + ranking: d.ranking,
389 + per_capita: d.per_capita,
390 + departamento: d.desc_departamento
391 + }));
392 + resumenCache[key] = mapped;
393 + resumen = mapped;
394 + } catch {
383 resumen = []; 395 resumen = [];
396 + }
397 + }
384 poblacionMap = await getPoblacionAno(gestion); 398 poblacionMap = await getPoblacionAno(gestion);
385 } 399 }
386 400
...@@ -668,7 +682,7 @@ ...@@ -668,7 +682,7 @@
668 <path d={pathGen(mapaData.bolivia)} class="mapa-pais-fill" /> 682 <path d={pathGen(mapaData.bolivia)} class="mapa-pais-fill" />
669 <path d={pathGen(mapaData.bolivia)} class="mapa-pais-outline" /> 683 <path d={pathGen(mapaData.bolivia)} class="mapa-pais-outline" />
670 {#each mapaData.municipios.features as feat} 684 {#each mapaData.municipios.features as feat}
671 - {@const cod = clasificadorSeleccionado !== 'total' ? feat.properties.ubigeo : String(feat.properties.codigo)} 685 + {@const cod = feat.properties.ubigeo}
672 {@const datos = datosPorCodigo[cod]} 686 {@const datos = datosPorCodigo[cod]}
673 {@const visible = enRango(cod)} 687 {@const visible = enRango(cod)}
674 {@const color = datos && visible ? colorScale(datos.valor) : 'transparent'} 688 {@const color = datos && visible ? colorScale(datos.valor) : 'transparent'}
......