finanzas-personales

Finanzas Personales compatible con Banco Santander Chile.

RepositorioÚltima versión: v1.0.0Ver como Markdown

Estadísticas

Estrellas
★ 1
Forks
⑂ 0
Issues abiertos
0
Licencia
MIT
Última actualización
Creado
Tamaño
1,3 MB

Lenguajes

  • Python 69,8%
  • JavaScript 30,2%

Temas

  • finance
  • financial-analysis
  • santander

Clonar

git clone https://github.com/KikeMuller/finanzas-personales.git

README

Se muestra en su idioma original.

El dashboard de finanzas personales

Las cifras, las escalas, los nombres de comercio y los dígitos de las tarjetas están tapados: son datos reales.

💵 Finanzas Personales

Tus finanzas, construidas desde los estados de cuenta del banco.

Un solo archivo que se abre con doble clic.
Sin instalar nada, sin servidor y sin internet. Ningún dato sale de tu computador.


Descargar el dashboard

Banco Santander Chile Funciona sin internet Sin instalación


1. Partir de cero

  1. Descarga el dashboard con el botón de arriba. Es un archivo, dashboard_vacio.html.

  2. Ábrelo con doble clic. No hay paso de instalación: se abre en tu navegador y ya funciona.

  3. Dile quién eres. En la pestaña Datos, en el JSON de reglas, agrega tu nombre y tu RUT:

    "titular": ["NOMBRE APELLIDO"],
    "titular_rut": ["12345678-9"]
    

    Esto va antes de cargar los archivos, porque el tipo de cada movimiento se decide al leerlos. Sin esto, las transferencias entre tus propias cuentas se cuentan como ingresos y los totales quedan inflados.

  4. Arrastra tus estados de cuenta sobre la página. Se procesan en tu computador, sin subir nada.

  5. Aprieta ⤓ Guardar HTML con datos. Esa copia, con tus datos adentro, pasa a ser tu dashboard de aquí en adelante. Si cierras sin guardar, se pierde lo que cargaste.

Por ahora solo es compatible con Banco Santander Chile. Los extractores están escritos contra el formato exacto de sus cartolas y estados de tarjeta; documentos de otro banco no se van a leer.


2. Uso diario

  1. Doble clic en dashboard.html.
  2. Tres pestañas:
    • Dashboard — indicadores, gráficos, alertas y conciliación de caja.
    • Detalle — todos los movimientos, filtrables por mes, origen, categoría, tipo y texto.
    • Datos — cargar archivos, ver la verificación y editar las reglas de categorización.
  3. Los filtros de arriba (desde / hasta / origen / categoría) afectan a las dos primeras pestañas.

Agregar meses nuevos

  1. Descarga los tres documentos desde el sitio del banco:

    • la cartola de cuenta corriente del mes, en .xlsx;
    • los estados de las dos tarjetas, en .pdf.

    No sirven los estados que llegan por correo: vienen protegidos con contraseña y el dashboard no puede abrirlos. Tienen que bajarse desde la página.

  2. Arrástralos sobre la página, en la pestaña Datos.

  3. Revisa el recuadro de verificación: debe decir Todo cuadra.

  4. Aprieta ⤓ Guardar HTML con datos y deja esa copia en lugar de dashboard.html.

Si cargas un archivo que ya estaba, reemplaza al anterior en lugar de duplicarlo. Eso permite volver a cargar un mes corregido sin ensuciar los datos.

Nada se guarda solo

Los datos viven dentro del propio dashboard.html. Lo que cargues, edites o vacíes existe únicamente mientras la pestaña está abierta: si la cierras sin guardar, al volver a abrir el archivo reaparece exactamente lo que había antes. Una página web no puede modificar por su cuenta un archivo de tu disco.

Por eso, cuando hay cambios pendientes aparece arriba a la derecha el aviso ● Cambios sin guardar y el navegador pregunta antes de cerrar la pestaña.

Al apretar ⤓ Guardar HTML con datos, en Chrome y Edge se abre el diálogo de guardar y puedes elegir el propio dashboard.html para sobrescribirlo. En los navegadores que no lo permiten, el archivo cae en Descargas y tienes que reemplazarlo tú.

Esto también aplica al botón Vaciar datos de esta pestaña: vacía la vista, pero el archivo queda igual hasta que guardes la versión vacía encima.

Nombres de archivo

Los PDF se identifican por su contenido, así que da lo mismo cómo se llamen. Las cartolas sí dependen del nombre para saber a qué mes corresponden: debe conservar el formato del banco, ... - <Mes> <Año>.xlsx (por ejemplo Cartola de cuenta Corriente - Marzo 2026.xlsx).


3. Cómo funciona

PDF / XLSX  ─►  parser.js  ─►  movimientos  ─►  agregados.js  ─►  gráficos y tablas
                    │                                 │
              verificación                     dashboard.html
           contra totales del banco        (todo esto va adentro)
Pieza Rol
dashboard.html El entregable. ~2,1 MB. Lleva adentro los datos, la interfaz y las librerías.
dashboard_vacio.html La misma página sin un solo dato. Es el punto de partida para alguien nuevo.
scripts/parser.js Lee cartolas y estados de tarjeta, clasifica cada movimiento y verifica los totales.
scripts/agregados.js Convierte los movimientos en KPIs, series mensuales, recurrentes, alertas y conciliación.
scripts/reglas_categorias.json Reglas de categorización, tipo de cambio y cuentas propias.
scripts/vendor/ PDF.js, fflate y Chart.js, que se incrustan en el HTML. Licencias en LICENSES.txt.
scripts/build_dashboard.py Rearma dashboard.html desde cero. Solo para desarrollo.
scripts/actualizar_dolar.py Trae el dólar observado del SII y actualiza el tipo de cambio.
scripts/extract.py Extractor original en Python. Respaldo y control cruzado.
scripts/test_parser.mjs Compara el parser JS contra el de Python, movimiento a movimiento.
data/transacciones.csv Los movimientos en CSV, para abrir en Excel.
data/resumen.json Dataset completo con los metadatos de cada documento.

PDF.js normalmente descarga en segundo plano un archivo aparte para procesar los PDF; acá viene incrustado y se ejecuta en el hilo principal, por eso funciona sin internet y al abrir el archivo directamente desde el disco. Procesar un año entero de documentos toma menos de un segundo.


4. Criterios de cálculo

Vale la pena entenderlos para leer bien los números.

Gasto real = compras de las tarjetas

Los cargos Traspaso Internet a T. Crédito de la cuenta corriente se marcan como pago_tarjeta y no se cuentan como gasto. Si se contaran, cada compra aparecería dos veces: una en el detalle de la tarjeta y otra al pagar la factura a fin de mes.

Dos vistas de resultado, las dos correctas

  • Balance devengado (el KPI): ingresos − gastos del mes en que ocurrieron. Sirve para saber en qué se va la plata.
  • Conciliación de caja (la tabla): lo que efectivamente entró y salió de la cuenta corriente. Cuadra peso a peso con el saldo inicial y final de cada cartola.

La diferencia entre ambas es deuda de tarjeta (compras que se pagan el mes siguiente o se refinancian en cuotas) más plata movida entre cuentas propias. Por eso el balance devengado puede ser negativo mientras el saldo de la cuenta sube.

Movimientos internacionales

Si el estado internacional trae el monto original en pesos, se usa ese monto tal cual. Si viene en otra moneda, se convierte desde USD con el tipo_cambio_usd_clp de las reglas. En la práctica eso afecta a una minoría de los movimientos: la mayoría ya viene convertida por el banco.

Ese valor se refresca con el dólar observado del SII:

python scripts/actualizar_dolar.py            # último valor publicado
python scripts/actualizar_dolar.py --dry-run  # muestra qué haría, sin escribir

Es un paso de desarrollo, no del dashboard: la página corre sin red por diseño y no puede consultar al SII sola. Después hay que regenerar con extract.py y build_dashboard.py.

Se usa un solo valor para todo el período, no el del día de cada compra. Mientras sean pocos movimientos la diferencia es marginal; si algún día pesa más, conviene pasar a convertir cada movimiento con el dólar de su fecha.

Meses parciales

Los meses sin cartola de cuenta corriente solo tienen compras de tarjeta: aparecen marcados bajo el gráfico de flujo y no deben leerse como meses sin ingresos. Suele pasar en el primer y el último mes del período, cuando todavía no descargaste la cartola correspondiente.


5. Diccionario de tipos

Cada movimiento tiene un tipo, que determina si suma al gasto, al ingreso o a ninguno. Los montos positivos son salidas de plata; los negativos, entradas.

Tipo Qué es ¿Cuenta como gasto?
gasto Compra en un comercio. Sí
cargo_financiero Intereses, comisiones, impuestos y cargos por uso internacional. Sí
reembolso Notas de crédito y devoluciones. Se resta del gasto bruto. Resta
ingreso Remuneración, devoluciones de impuestos, transferencias recibidas de terceros. Es ingreso
traspaso_interno Plata movida entre cuentas propias o a la línea de crédito. No
pago_tarjeta Pago de la factura de la tarjeta desde la cuenta corriente. No (evita doble conteo)
financiamiento Refinanciamientos: traspaso de deuda a cuotas, monto cancelado, traspaso a deuda nacional. No

Las categorías (Supermercado y almacén, Delivery de comida, etc.) son una capa aparte, editable. Los tipos ingreso, traspaso_interno, pago_tarjeta, financiamiento y reembolso reciben categoría fija; solo gasto y cargo_financiero pasan por las reglas.


6. Categorización

En la pestaña Datos están las reglas en JSON y, al lado, la lista de movimientos sin clasificar ordenada por monto. El flujo es:

  1. Buscas un comercio en la lista de la derecha.
  2. Lo agregas a la categoría que corresponda en el JSON de la izquierda.
  3. Aprietas Aplicar reglas: recategoriza al instante, sin volver a leer los PDF.
  4. Exportas el HTML para conservarlo.

Las reglas se evalúan en orden y la primera que calza gana, así que las específicas van arriba. Los patrones se comparan en mayúsculas y sin acentos contra la descripción completa del movimiento, como texto contenido (no hace falta el nombre exacto).

Además de reglas, el JSON tiene:

Campo Para qué sirve
tipo_cambio_usd_clp Conversión de compras internacionales cuando el estado no trae pesos.
titular Nombres tuyos. Las transferencias a esos nombres se marcan como traspaso interno.
titular_rut Lo mismo, pero por RUT: más confiable, porque el banco escribe el nombre de varias formas.
tarjetas Opcional. Alias por los cuatro últimos dígitos, si no te gusta el nombre que trae el PDF.

Un movimiento marcado como traspaso interno no cuenta ni como ingreso ni como gasto. Sin esto, mover plata desde tu cuenta de ahorro aparecería como sueldo extra.

titular, titular_rut y tarjetas no están en reglas_categorias.json sino en scripts/titular.local.json, que queda fuera del repositorio por ser datos personales. Los scripts lo fusionan sobre las reglas si existe; si falta, avisan y siguen corriendo, pero esos traspasos pasan a contarse como ingresos. Para reconstruirlo hay una plantilla en scripts/titular.local.example.json.

Nombres de las tarjetas

No hay ninguna tarjeta escrita en el código. El nombre sale del propio estado de cuenta, de la línea Nº DE TARJETA DE CRÉDITO XXXX XXXX XXXX 1234 VISA PLATINUM LATAM, y queda como Visa Platinum Latam ...1234. Si prefieres llamarlas de otra forma, el campo tarjetas de titular.local.json las reemplaza:

"tarjetas": { "1234": "La de los viajes" }

7. Verificación

Cada vez que se leen documentos, se comparan contra los totales que declara el banco:

Documento Qué se cuadra
Cartola saldo inicial + abonos − cargos = saldo final
Tarjeta nacional 1. TOTAL OPERACIONES y 3. CARGOS, COMISIONES, IMPUESTOS Y ABONOS
Tarjeta internacional TOTAL DE COMPRAS Y CARGOS en USD

El resultado sale en la pestaña Datos y al pie de la página. El objetivo es siempre el mismo: cero diferencias en todos los documentos.

Esto es lo que hay que mirar al cargar un mes nuevo: si el banco cambia el formato de sus documentos, la diferencia aparece de inmediato en vez de pasar como un número silenciosamente equivocado.


8. Si algo falla

Síntoma Causa probable y qué hacer
"No pude leer el mes del nombre del archivo" La cartola fue renombrada. Devuélvele el formato ... - Marzo 2026.xlsx.
Un PDF no carga o da error al abrirlo Casi seguro es el estado que llega por correo, que viene con contraseña. Descárgalo desde la página del banco.
Los documentos no son de Santander Chile No están soportados: los extractores leen el formato específico de ese banco.
Aparece una diferencia en la verificación El banco cambió el formato del documento. El movimiento que falta se ve comparando el total del PDF con el de la pantalla; avísame y ajusto el parser.
Muchos movimientos sin clasificar Normal al cargar meses nuevos con comercios nuevos. Agrégalos a las reglas.
Un mes muestra gasto pero cero ingresos Falta la cartola de cuenta corriente de ese mes.
Los gráficos no aparecen El archivo quedó a medio descargar. Vuelve a guardarlo o rearma con build_dashboard.py.
Vaciaste los datos y al reabrir siguen ahí Es lo esperado: vaciar solo afecta a la pestaña. Hay que guardar el HTML vacío y reemplazar con él al archivo anterior.
Cargaste archivos y al reabrir no están Lo mismo: faltó guardar. El aviso ● Cambios sin guardar arriba a la derecha avisa cuando queda algo pendiente.
Guardaste y quedaron dos archivos El navegador no dejó sobrescribir y lo mandó a Descargas. El bueno es el recién descargado.

9. Trabajar el proyecto con Claude Code

cd D:\dev\Finanzas_Personales
claude

CLAUDE.md le da el contexto: arquitectura, los criterios de cálculo que no se pueden romper y por qué existen dos implementaciones del extractor. Hay cuatro comandos propios en .claude/commands/:

Comando Qué hace
/rebuild Regenera dashboard.html desde los estados de cuenta y verifica que todo cuadre.
/verificar Corre la verificación contra los totales del banco y la paridad JS ↔ Python.
/nuevo-mes Incorpora los documentos de un mes, revisa que cuadren y propone reglas para lo nuevo.
/categorias Revisa lo que quedó sin clasificar y propone reglas.

Ejemplos de lo que sirve pedirle: "agrega un gráfico de gasto por día de la semana", "el estado de agosto no cuadra, revisa qué movimiento se está perdiendo", "¿en qué categoría subí más respecto al trimestre pasado?".

Dos cosas configuradas a propósito:

  • .gitignore deja fuera los estados de cuenta, el CSV y el dashboard con datos. Si algún día inicias git, el historial no guarda información financiera.
  • .claude/settings.json bloquea la lectura directa de Datos Ejemplo/, para que un estado de cuenta completo no termine en el contexto sin querer. Para depurar un documento se usa pdfplumber desde la terminal. Si te estorba, borra esa línea del archivo.

10. Los scripts de Python (opcionales)

El pipeline en Python fue el original y se mantiene como respaldo y control cruzado. Ya no hace falta para usar el dashboard.

python scripts/extract.py                    # PDF/XLSX -> data/transacciones.csv y data/resumen.json
python scripts/build_dashboard.py            # rearma dashboard.html desde cero
python scripts/build_dashboard.py --vacio    # dashboard_vacio.html, sin datos, para compartir
python scripts/actualizar_dolar.py           # refresca el tipo de cambio desde el SII

extract.py requiere openpyxl y pdfplumber; actualizar_dolar.py no necesita nada instalado, pero sí internet. build_dashboard.py corre aunque no exista data/resumen.json: en ese caso genera el dashboard vacío.

--vacio no incrusta titular.local.json, así que esa copia no lleva tu nombre, tu RUT ni los alias de tus tarjetas. Es la que se puede publicar.

El botón de descarga del principio apunta al último release, no al archivo del repositorio: GitHub sirve los .html como texto plano, así que un enlace al archivo lo abriría en pantalla en vez de descargarlo. Eso significa que el asset del release es una copia congelada: al regenerar dashboard_vacio.html hay que publicarlo de nuevo, o la gente se sigue bajando el anterior.

gh release create v1.1.0 dashboard_vacio.html --title "..." --notes "..."

Para comprobar que el parser del navegador sigue dando exactamente lo mismo que Python:

cd scripts && npm i && node test_parser.mjs

scripts/package.json fija pdfjs-dist en la versión exacta que hay en scripts/vendor/, sin ^. Si npm instalara una más nueva, la prueba dejaría de comparar contra la librería que realmente corre dentro del dashboard.

Hoy da paridad total: los dos extractores producen exactamente los mismos movimientos, las mismas categorías y los mismos totales, con cero diferencias contra lo que declara cada documento. Si algún día se toca el parser, esta prueba es la red de seguridad.

Node solo hace falta para esta prueba: parser.js está escrito para el navegador, y compararlo contra extract.py exige ejecutarlo fuera de él. El dashboard no lo necesita nunca. En Windows sin Node, sirve WSL:

wsl -e bash -lc "cd /mnt/d/dev/Finanzas_Personales && node scripts/test_parser.mjs"

Los avisos de DOMMatrix y Path2D al arrancar son normales: son el polyfill de canvas que PDF.js usa para dibujar páginas, y acá solo se extrae texto.

← Volver a proyectos