+server.js 3.47 KB
const API_BASE = 'http://136.112.29.74/api/finfun';

let cachedClasificador = null;
let cachedEstados = null;
let cachedTimestamp = 0;
const CACHE_TTL = 5 * 60 * 1000;

function getParent(finfun) {
  const idx = finfun.lastIndexOf('.');
  if (idx === -1) return null;
  return finfun.substring(0, idx);
}

async function loadAndCacheAll() {
  const now = Date.now();
  if (cachedEstados && (now - cachedTimestamp) < CACHE_TTL) return;

  const clasRes = await fetch(`${API_BASE}/clasificador`);
  if (!clasRes.ok) throw new Error('Failed to fetch clasificador');
  cachedClasificador = await clasRes.json();

  const estados = new Map();
  const batchSize = 80;

  for (let i = 0; i < cachedClasificador.length; i += batchSize) {
    const batch = cachedClasificador.slice(i, i + batchSize);
    const results = await Promise.all(batch.map(async (item) => {
      try {
        const res = await fetch(`${API_BASE}/${item.finfun}`);
        if (!res.ok) return null;
        const data = await res.json();
        return { finfun: item.finfun, estados: data.estados || [] };
      } catch { return null; }
    }));
    results.filter(Boolean).forEach(r => estados.set(r.finfun, r.estados));
  }

  cachedEstados = estados;
  cachedTimestamp = now;
}

export async function GET({ url }) {
  const gestion = parseInt(url.searchParams.get('gestion') || '2025');
  const entidad = url.searchParams.get('entidad') || '0';

  try {
    if (entidad === '0') {
      await loadAndCacheAll();

      const results = [];
      for (const item of cachedClasificador) {
        const estados = cachedEstados.get(item.finfun);
        if (!estados) continue;
        const yearData = estados.find(d => d.gestion === gestion);
        if (!yearData || !yearData.total) continue;
        results.push({
          gestion,
          nivel: item.nivel,
          finfun: item.finfun,
          desc_finfun: item.desc_finfun,
          parent: getParent(item.finfun),
          devengado: yearData.total
        });
      }

      return new Response(JSON.stringify(results), {
        headers: { 'Content-Type': 'application/json' }
      });
    } else {
      if (!cachedClasificador) {
        const clasRes = await fetch(`${API_BASE}/clasificador`);
        cachedClasificador = await clasRes.json();
      }

      const results = [];
      const batchSize = 80;

      for (let i = 0; i < cachedClasificador.length; i += batchSize) {
        const batch = cachedClasificador.slice(i, i + batchSize);
        const batchResults = await Promise.all(batch.map(async (item) => {
          try {
            const res = await fetch(`${API_BASE}/${item.finfun}/entidades/${entidad}`);
            if (!res.ok) return null;
            const data = await res.json();
            const yearData = data.find(d => d.gestion === gestion);
            if (!yearData || !yearData.monto) return null;
            return {
              gestion,
              nivel: item.nivel,
              finfun: item.finfun,
              desc_finfun: item.desc_finfun,
              parent: getParent(item.finfun),
              devengado: yearData.monto
            };
          } catch { return null; }
        }));
        results.push(...batchResults.filter(Boolean));
      }

      return new Response(JSON.stringify(results), {
        headers: { 'Content-Type': 'application/json' }
      });
    }
  } catch (err) {
    return new Response(JSON.stringify({ error: 'Failed to build treemap' }), {
      status: 500, headers: { 'Content-Type': 'application/json' }
    });
  }
}