Rafael Lopez

descargas

# Lógica del Buscador
## Resumen
Buscador instantáneo con Fuse.js en cliente. Busca en clasificadores presupuestarios y navega a vistas de detalle.
## Decisiones de Diseño
### Motor de búsqueda
- **Tecnología**: Fuse.js (cliente)
- **Razón**: ~1,400 registros totales (~600 entidades + ~450 objetos + ~380 rubros), cabe en memoria, búsqueda instantánea sin latencia
### Configuración Fuse.js
```javascript
const fuseOptions = {
keys: [
{ name: 'nombre_normalizado', weight: 0.6 },
{ name: 'sigla_normalizada', weight: 0.2 },
{ name: 'codigo_normalizado', weight: 0.2 }
],
threshold: 0.4,
distance: 100,
includeScore: true,
includeMatches: true,
minMatchCharLength: 2,
ignoreLocation: true
};
```
### Tolerancia a errores
- Normalización de acentos ("andres" → "andrés")
- Case-insensitive ("UMSA" = "umsa")
- Fuzzy matching ("univercidad" → "universidad")
### Comportamiento
| Parámetro | Valor |
|-----------|-------|
| Debounce | 250ms |
| Mínimo caracteres | 2 |
| Máximo resultados | 15 |
| Navegación | Flechas ↑↓ + Enter + scroll de mouse |
## Estructura del Índice
### Índice unificado (implementado)
Todos los clasificadores en un solo array con `tipo`:
```javascript
// src/lib/services/search.js
const searchData = [
// Entidades
{
tipo: 'entidad',
codigo: 139,
nombre: 'Universidad Mayor De San Andrés',
sigla: 'UMSA',
contexto: 'Universidades Públicas',
años: 20,
nombre_normalizado: 'universidad mayor de san andres',
sigla_normalizada: 'umsa',
codigo_normalizado: '139'
},
// Objetos de gasto
{
tipo: 'objeto_gasto',
codigo: '25100',
nombre: 'Pasajes',
sigla: null,
contexto: 'Objeto del Gasto · Partida',
nivel: 'partida',
nombre_normalizado: 'pasajes',
sigla_normalizada: '',
codigo_normalizado: '25100'
},
// Rubros
{
tipo: 'rubro',
codigo: 13000,
nombre: 'INGRESOS POR IMPUESTOS',
sigla: null,
contexto: 'Rubro · Tipo',
nivel: 'tipo',
nombre_normalizado: 'ingresos por impuestos',
sigla_normalizada: '',
codigo_normalizado: '13000'
}
]
```
### Fuentes de datos
- **Entidades**: tabla `ppto.clas_institucional`
- **Objetos de gasto**: tabla `ppto.clas_objetos`
- **Rubros**: tabla `ppto.clas_rubros`
## Columnas de Búsqueda
### Entidades (clas_institucional)
| Columna | Buscar | Mostrar |
|---------|--------|---------|
| `desc_entidad` | ✓ | ✓ nombre principal |
| `sigla_entidad` | ✓ | ✓ entre paréntesis |
| `desc_area` | ✗ | ✓ contexto |
| `n_gestiones` | ✗ | ✓ "X años de datos" |
| `entidad` | ✗ | para URL |
### Objetos de gasto (clas_objetos)
| Columna | Buscar | Mostrar |
|---------|--------|---------|
| `desc_objeto` | ✓ | ✓ nombre principal |
| `objeto` | ✓ | ✓ código (monospace) |
| `nivel` | ✗ | ✓ contexto ("Objeto del Gasto · Partida") |
### Rubros (clas_rubros)
| Columna | Buscar | Mostrar |
|---------|--------|---------|
| `desc_rubros` | ✓ | ✓ nombre principal |
| `rubro` | ✓ | ✓ código (monospace) |
| `nivel` | ✗ | ✓ contexto ("Rubro · Tipo") |
## Flujo de Búsqueda
```
1. CARGA INICIAL
App monta → descarga clasificadores → construye índice Fuse.js
2. USUARIO ESCRIBE
Input → debounce 250ms → si ≥2 chars → Fuse.search()
3. RESULTADOS
Fuse devuelve matches → renderizar lista con highlighting
4. SELECCIÓN
Click o Enter → navegar a URL según tipo
```
## Estructura de URLs
```
/entidad/[codigo] → /entidad/139
/objeto/[codigo] → /objeto/25100
/rubro/[codigo] → /rubro/13000
```
## Formato de Resultados
Resultados agrupados por tipo de clasificador:
```
┌─────────────────────────────────────────────────────┐
│ 🔍 [Buscar entidad, objeto de gasto o rubro...] │
├─────────────────────────────────────────────────────┤
│ ENTIDADES │
├─────────────────────────────────────────────────────┤
│ Universidad Mayor De San Andrés (UMSA) │
│ Universidades Públicas │
├─────────────────────────────────────────────────────┤
│ OBJETOS DEL GASTO │
├─────────────────────────────────────────────────────┤
│ 25100 Pasajes │
│ Objeto del Gasto · Partida │
├─────────────────────────────────────────────────────┤
│ RUBROS │
├─────────────────────────────────────────────────────┤
│ 13000 INGRESOS POR IMPUESTOS │
│ Rubro · Tipo │
└─────────────────────────────────────────────────────┘
```
### Diferencias visuales
- **Entidades**: Nombre + (sigla) en primera línea
- **Objetos de gasto**: Código (monospace) + Nombre en primera línea
- **Rubros**: Código (monospace) + Nombre en primera línea
## Estados del Buscador
| Estado | Qué mostrar |
|--------|-------------|
| Vacío (< 2 chars) | Placeholder o sugerencias |
| Cargando índice | Spinner / "Cargando..." |
| Buscando | Nada (es instantáneo) |
| Con resultados | Lista de resultados |
| Sin resultados | "No se encontraron resultados para 'xyz'" |
| Error | "Error al cargar datos" |
## Estructura de Archivos
```
src/lib/
├── components/
│ └── search/
│ ├── SearchBox.svelte ← Input + lógica de búsqueda
│ ├── SearchResults.svelte ← Lista de resultados
│ └── SearchResultItem.svelte ← Item individual
├── services/
│ ├── supabase.js ← Cliente Supabase
│ └── search.js ← Inicialización Fuse.js
├── stores/
│ └── searchStore.js ← Estado: query, results, loading
├── utils/
│ └── normalize.js ← Normalización de texto
└── data/
└── index.js ← Carga y construcción del índice
```
## Estado de Implementación
| Clasificador | Estado | Tabla |
|--------------|--------|-------|
| Entidades | ✅ Implementado | `ppto.clas_institucional` |
| Objetos de gasto | ✅ Implementado | `ppto.clas_objetos` |
| Rubros | ✅ Implementado | `ppto.clas_rubros` |
| Fuente de financiamiento | ⏳ Pendiente | - |
| Geográfico | ⏳ Pendiente | - |
## Trabajo Futuro
### Índice pre-computado
Posibilidad de pre-computar el índice en servidor y servir como JSON estático para mejorar tiempo de carga inicial.
### Migración a servidor
Si el índice supera ~20,000 registros:
1. Habilitar extensión `pg_trgm` en PostgreSQL
2. Crear índices GIN en columnas de búsqueda
3. Cambiar de Fuse.js a queries con `similarity()` o `%` operator
4. El componente de UI se mantiene igual, solo cambia el servicio
---
*Documento de referencia para la implementación del buscador*
export const ssr = false;
# Estructura de Bases de Datos - Presupuesto Público Bolivia
Este documento detalla las tablas, vistas y sus estructuras en el esquema `ppto` de Supabase.
---
## Tablas de Clasificadores
### 1. `clas_institucional` - Clasificador Institucional
| Columna | Tipo | Descripción |
|---------|------|-------------|
| entidad | INTEGER | Código único de la entidad |
| desc_entidad | TEXT | Nombre completo de la entidad |
| sigla_entidad | VARCHAR(50) | Sigla de la entidad |
| sector | VARCHAR(10) | Código del sector |
| desc_sector | TEXT | Nombre del sector |
| sigla_sector | VARCHAR(20) | Sigla del sector |
| subsector | VARCHAR(10) | Código del subsector |
| desc_subsector | TEXT | Nombre del subsector |
| sigla_subsector | VARCHAR(20) | Sigla del subsector |
| area | VARCHAR(10) | Código del área |
| desc_area | TEXT | Nombre del área |
| sigla_area | VARCHAR(20) | Sigla del área |
| subarea | VARCHAR(10) | Código de la subárea |
| desc_subarea | TEXT | Nombre de la subárea |
| sigla_subarea | VARCHAR(20) | Sigla de la subárea |
| gestiones | TEXT | Lista CSV de años con datos (ej: "2006,2007,...,2025") |
| n_gestiones | INTEGER | Cantidad de años con datos |
---
### 2. `clas_objetos` - Clasificador de Objetos de Gasto
| Columna | Tipo | Descripción |
|---------|------|-------------|
| nivel | TEXT | Nivel jerárquico: 'grupo', 'subgrupo', 'partida', 'subpartida' |
| objeto | TEXT (PK) | Código del objeto (ej: "10000", "11000", "11100") |
| desc_objeto | TEXT | Descripción vigente del objeto de gasto |
| gestiones | TEXT | Rangos de años donde existe (ej: "2005, 2007-2020, 2022-2026") |
| n_gestiones | INTEGER | Cantidad de años con datos |
| n_variaciones | INTEGER | Cantidad de variaciones históricas en la descripción |
| descripciones | JSONB | Historial de descripciones por rangos de años |
**Estructura de `descripciones`:**
```json
[
{
"descripcion": "Descripción vigente del objeto...",
"rangos": "2011-2020, 2022-2026"
},
{
"descripcion": "Descripción anterior del objeto...",
"rangos": "2005, 2007-2010"
}
]
```
**Jerarquía derivada del código `objeto`:**
```
Nivel Patrón Ejemplo
─────────────────────────────────
grupo X0000 10000, 20000
subgrupo XX000 11000, 12000
partida XXX00 11100, 11200
subpartida XXXX0/X 11110, 11111
```
**Sin índices.** La tabla tiene ~500 filas y se carga completa al inicio.
---
### 3. `clas_rubros` - Clasificador de Rubros (Ingresos)
| Columna | Tipo | Descripción |
|---------|------|-------------|
| nivel | TEXT | Nivel jerárquico: 'tipo', 'clase', 'cuenta', 'sub_cuenta' |
| rubro | TEXT (PK) | Código del rubro (ej: "1000", "1100", "1110") |
| desc_rubro | TEXT | Descripción vigente del rubro |
| gestiones | TEXT | Rangos de años donde existe (ej: "2005, 2007-2020, 2022-2026") |
| n_gestiones | INTEGER | Cantidad de años con datos |
| n_variaciones | INTEGER | Cantidad de variaciones históricas en la descripción |
| descripciones | JSONB | Historial de descripciones por rangos de años |
**Estructura de `descripciones`:**
```json
[
{
"descripcion": "Descripción vigente del rubro...",
"rangos": "2011-2020, 2022-2026"
},
{
"descripcion": "Descripción anterior del rubro...",
"rangos": "2005, 2007-2010"
}
]
```
**Jerarquía derivada del código `rubro`:**
```
Nivel Patrón Ejemplo
──────────────────────────────────
tipo X000 1000, 2000
clase XX00 1100, 1200
cuenta XXX0 1110, 1120
sub_cuenta XXXX 1111, 1112
```
**Sin índices.** La tabla tiene ~400 filas y se carga completa al inicio.
---
### 4. `clas_finfun` - Clasificador de Finalidad y Función
| Columna | Tipo | Descripción |
|---------|------|-------------|
| nivel | TEXT | Nivel jerárquico: 'finalidad', 'grpfuncion', 'funcion' |
| finfun | TEXT (PK) | Código de finalidad/función (ej: "1", "11", "111") |
| desc_finfun | TEXT | Descripción vigente de la finalidad/función |
| gestiones | TEXT | Rangos de años donde existe (ej: "2005, 2007-2020, 2022-2026") |
| n_gestiones | INTEGER | Cantidad de años con datos |
| n_variaciones | INTEGER | Cantidad de variaciones históricas en la descripción |
| descripciones | JSONB | Historial de descripciones por rangos de años |
**Estructura de `descripciones`:**
```json
[
{
"descripcion": "Descripción vigente de la finalidad/función...",
"rangos": "2011-2020, 2022-2026"
},
{
"descripcion": "Descripción anterior...",
"rangos": "2005, 2007-2010"
}
]
```
**Jerarquía derivada del código `finfun`:**
```
Nivel Patrón Ejemplo
──────────────────────────────────
finalidad X 1, 2, 3
grpfuncion XX 11, 12, 21
funcion XXX+ 111, 112, 211
```
**Sin índices.** La tabla tiene ~200 filas y se carga completa al inicio.
---
## Tablas de Datos Agregados
### 5. `treemap_objeto` - Datos para Treemap de Objetos de Gasto
| Columna | Tipo | Descripción |
|---------|------|-------------|
| gestion | INTEGER | Año fiscal (2005-2025) |
| entidad | INTEGER | Código de entidad (0 = Todo el Estado) |
| nivel | VARCHAR(20) | Nivel: 'grupo', 'subgrupo', 'partida', 'subpartida' |
| objeto | INTEGER | Código del objeto |
| desc_objeto | TEXT | Descripción del objeto |
| parent | INTEGER | Código del objeto padre (para jerarquía) |
| devengado | NUMERIC | Monto devengado en Bs |
**Índices recomendados:**
```sql
CREATE INDEX idx_treemap_objeto_gestion_entidad ON ppto.treemap_objeto(gestion, entidad);
```
**Notas:**
- ~1.4 millones de filas
- Entidad 0 representa el agregado de todo el estado
- Cada combinación gestión + entidad debe cargarse como unidad
---
### 6. `entidades_treemap` - Índice de Entidades por Año (Treemap)
| Columna | Tipo | Descripción |
|---------|------|-------------|
| entidad | INTEGER | Código de la entidad |
| gestion | INTEGER | Año fiscal |
| desc_entidad | TEXT | Nombre de la entidad |
| sigla_entidad | VARCHAR(50) | Sigla de la entidad |
**Índices recomendados:**
```sql
CREATE INDEX idx_entidades_treemap_gestion ON ppto.entidades_treemap(gestion);
```
**SQL para crear (derivada de treemap_objeto):**
```sql
CREATE TABLE ppto.entidades_treemap AS
SELECT DISTINCT
t.entidad,
t.gestion,
c.desc_entidad,
c.sigla_entidad
FROM ppto.treemap_objeto t
LEFT JOIN ppto.clas_institucional c ON t.entidad = c.entidad
WHERE t.entidad > 0;
CREATE INDEX idx_entidades_treemap_gestion ON ppto.entidades_treemap(gestion);
GRANT SELECT ON ppto.entidades_treemap TO anon, authenticated;
```
**Uso:** Poblar dropdown de entidades filtrado por año seleccionado.
---
### 7. `entidades_por_objeto` - Relación Entidades-Objetos
| Columna | Tipo | Descripción |
|---------|------|-------------|
| entidad | INTEGER | Código de la entidad |
| entidad_desc | TEXT | Nombre de la entidad |
| objeto | INTEGER | Código del objeto |
| nivel | VARCHAR(20) | Nivel del objeto |
**Índices recomendados:**
```sql
CREATE INDEX idx_entidades_por_objeto_objeto ON ppto.entidades_por_objeto(objeto);
CREATE INDEX idx_entidades_por_objeto_objeto_nivel ON ppto.entidades_por_objeto(objeto, nivel);
```
**Uso:** Poblar dropdowns de entidades al ver un objeto específico.
---
### 8. `vista_finfun_estado` - Vista Agregada por Finalidad/Función (Todo el Estado)
| Columna | Tipo | Descripción |
|---------|------|-------------|
| gestion | INTEGER | Año fiscal |
| finfun | TEXT | Código de finalidad/función |
| total | NUMERIC | Monto total devengado |
| poblacion | INTEGER | Población del año |
| n_entidades | INTEGER | Cantidad de entidades con datos |
| per_capita | NUMERIC | Gasto per cápita (total/población) |
| total_gestion | NUMERIC | Total del Estado en esa gestión |
| prop | NUMERIC | Proporción sobre el total del Estado |
| ranking | INTEGER | Ranking por monto dentro de su nivel |
| n_pares | INTEGER | Cantidad de códigos del mismo nivel |
| top1_entidad | INTEGER | Código de la entidad con mayor gasto |
| top1_entidad_desc | TEXT | Nombre de la entidad top 1 |
| top1_monto | NUMERIC | Monto de la entidad top 1 |
| top1_pct | NUMERIC | Porcentaje del total |
| top2_entidad | INTEGER | Código de la entidad top 2 |
| top2_entidad_desc | TEXT | Nombre de la entidad top 2 |
| top2_monto | NUMERIC | Monto de la entidad top 2 |
| top2_pct | NUMERIC | Porcentaje del total |
| top3_entidad | INTEGER | Código de la entidad top 3 |
| top3_entidad_desc | TEXT | Nombre de la entidad top 3 |
| top3_monto | NUMERIC | Monto de la entidad top 3 |
| top3_pct | NUMERIC | Porcentaje del total |
**Índices recomendados:**
```sql
CREATE INDEX idx_vista_finfun_estado_finfun ON ppto.vista_finfun_estado(finfun);
CREATE INDEX idx_vista_finfun_estado_finfun_gestion ON ppto.vista_finfun_estado(finfun, gestion);
```
---
### 9. `vista_finfun_entidad` - Vista por Finalidad/Función y Entidad
| Columna | Tipo | Descripción |
|---------|------|-------------|
| gestion | INTEGER | Año fiscal |
| finfun | TEXT | Código de finalidad/función |
| nivel | TEXT | Nivel: 'finalidad', 'grpfuncion', 'funcion' |
| entidad | INTEGER | Código de la entidad |
| entidad_desc | TEXT | Nombre de la entidad |
| monto | NUMERIC | Monto devengado |
| per_capita | NUMERIC | Gasto per cápita |
| ranking | INTEGER | Ranking de la entidad para ese finfun |
| prop | NUMERIC | Proporción sobre el total del finfun |
| n_entidades | INTEGER | Total de entidades con ese finfun |
**Índices recomendados:**
```sql
CREATE INDEX idx_vista_finfun_entidad_finfun ON ppto.vista_finfun_entidad(finfun);
CREATE INDEX idx_vista_finfun_entidad_finfun_entidad ON ppto.vista_finfun_entidad(finfun, entidad);
```
---
### 10. `entidades_por_finfun` - Relación Entidades-Finalidad/Función
| Columna | Tipo | Descripción |
|---------|------|-------------|
| finfun | TEXT | Código de finalidad/función |
| nivel | TEXT | Nivel: 'finalidad', 'grpfuncion', 'funcion' |
| entidad | INTEGER | Código de la entidad |
| entidad_desc | TEXT | Nombre de la entidad |
**Índices recomendados:**
```sql
CREATE INDEX idx_entidades_por_finfun_finfun ON ppto.entidades_por_finfun(finfun);
CREATE INDEX idx_entidades_por_finfun_finfun_nivel ON ppto.entidades_por_finfun(finfun, nivel);
```
**Uso:** Poblar dropdowns de entidades al ver una finalidad/función específica.
---
## Vistas Materializadas / Tablas de Consulta
### 11. `vista_objeto_estado` - Vista Agregada por Objeto (Todo el Estado)
| Columna | Tipo | Descripción |
|---------|------|-------------|
| objeto | INTEGER | Código del objeto |
| gestion | INTEGER | Año fiscal |
| devengado | NUMERIC | Monto total devengado |
| top1_entidad | TEXT | Entidad con mayor gasto |
| top1_monto | NUMERIC | Monto de la entidad top 1 |
| top1_pct | NUMERIC | Porcentaje del total |
| top2_entidad | TEXT | Segunda entidad con mayor gasto |
| top2_monto | NUMERIC | Monto de la entidad top 2 |
| top2_pct | NUMERIC | Porcentaje del total |
| top3_entidad | TEXT | Tercera entidad con mayor gasto |
| top3_monto | NUMERIC | Monto de la entidad top 3 |
| top3_pct | NUMERIC | Porcentaje del total |
**Índices recomendados:**
```sql
CREATE INDEX idx_vista_objeto_estado_objeto ON ppto.vista_objeto_estado(objeto);
CREATE INDEX idx_vista_objeto_estado_objeto_gestion ON ppto.vista_objeto_estado(objeto, gestion);
```
---
### 12. `vista_objeto_entidad` - Vista por Objeto y Entidad
| Columna | Tipo | Descripción |
|---------|------|-------------|
| objeto | INTEGER | Código del objeto |
| nivel | VARCHAR(20) | Nivel del objeto |
| entidad | INTEGER | Código de la entidad |
| gestion | INTEGER | Año fiscal |
| devengado | NUMERIC | Monto devengado |
**Índices recomendados:**
```sql
CREATE INDEX idx_vista_objeto_entidad_objeto ON ppto.vista_objeto_entidad(objeto);
CREATE INDEX idx_vista_objeto_entidad_objeto_entidad ON ppto.vista_objeto_entidad(objeto, entidad);
CREATE INDEX idx_vista_objeto_entidad_objeto_nivel_entidad ON ppto.vista_objeto_entidad(objeto, nivel, entidad);
```
---
## Jerarquías
### Objetos de Gasto (4 niveles)
```
Grupo (1xxxx) → Subgrupo (11xxx) → Partida (111xx) → Subpartida (11110)
```
### Rubros de Ingresos (4 niveles)
```
Tipo → Clase → Cuenta → Subcuenta
```
### Finalidad y Función (3 niveles)
```
Finalidad (X) → Grupo Función (XX) → Función (XXX)
```
### Institucional (5 niveles)
```
Sector → Subsector → Área → Subárea → Entidad
```
---
## Tablas de Vista de Entidad"
### 13. `entidad_resumen` - Resumen histórico por entidad/DA
Alimenta los gráficos de historia (area plots) y rankings en la vista de entidad (`/entidad/[codigo]`).
| Columna | Tipo | Descripción |
|---------|------|-------------|
| tipo | TEXT | Tipo de flujo: 'gastos' o 'ingresos' |
| tipo_codigo | TEXT | Tipo de código: 'entidad', 'entidad_da', 'municipio_ubigeo', etc. |
| codigo | TEXT | Código de la entidad o DA (ej: "1901", "1901.6") |
| desc | TEXT | Nombre de la entidad o DA |
| desc_padre | TEXT | Nombre de la entidad madre (para DAs) |
| gestion | INTEGER | Año fiscal |
| devengado | NUMERIC | Monto devengado en Bs |
| ranking | INTEGER | Posición en ranking por monto dentro de su tipo y gestión |
**Primary key:** `(tipo, tipo_codigo, codigo, gestion)`
**Índices:**
```sql
CREATE INDEX idx_entidad_resumen_codigo ON ppto.entidad_resumen (codigo);
CREATE INDEX idx_entidad_resumen_gestion ON ppto.entidad_resumen (gestion);
CREATE INDEX idx_entidad_resumen_tipo_codigo ON ppto.entidad_resumen (tipo_codigo);
```
**Notas:**
- ~53K filas
- `codigo` es TEXT para soportar entidades ("1901") y DAs ("1901.6")
- `desc` y `desc_padre` permiten resolver nombres sin joins ni búsquedas externas
- Una fila por combinación tipo + tipo_codigo + código + año
---
### 14. `entidad_distribuciones` - Distribución del gasto/ingreso por clasificador
Alimenta las barras de composición (clasificadores de gasto e ingreso) en la vista de entidad.
| Columna | Tipo | Descripción |
|---------|------|-------------|
| id | SERIAL (PK) | Identificador autoincremental |
| tipo | TEXT | Tipo de flujo: 'gastos' o 'ingresos' |
| tipo_codigo | TEXT | Tipo de código: 'entidad', 'entidad_da', etc. |
| codigo | TEXT | Código de la entidad o DA |
| dimension | TEXT | Clasificador: 'objeto', 'finfun', 'acteco', 'rubro', 'organismo' |
| gestion | INTEGER | Año fiscal |
| padre | TEXT | Código del grupo padre en la dimensión |
| desc_padre | TEXT | Descripción del grupo padre |
| hijo | TEXT | Código del ítem hijo |
| desc_hijo | TEXT | Descripción del ítem hijo |
| devengado | NUMERIC | Monto devengado en Bs |
**Índices:**
```sql
CREATE INDEX idx_entidad_dist_codigo ON ppto.entidad_distribuciones (codigo);
CREATE INDEX idx_entidad_dist_gestion ON ppto.entidad_distribuciones (gestion);
CREATE INDEX idx_entidad_dist_codigo_gestion ON ppto.entidad_distribuciones (codigo, gestion);
```
**Notas:**
- ~3.6M filas
- Usa `id SERIAL` como PK porque un mismo `hijo` puede tener distintas descripciones dentro de la misma combinación padre/gestión
- Cada fila es un segmento de las barras de composición: cuánto gastó/ingresó una entidad en un ítem específico de un clasificador en un año
---
*Documento generado para el equipo de sistemas - Marzo 2026*