Go to file
JKuijperM e814bc2d03 Anade filtro por tipo en objetivos y unifica la barra de progreso
El listado de objetivos mezclaba pagos, presupuestos y ahorros sin forma de
separarlos. Anade un filtro por tipo, con el mismo patron que los filtros de
gastos, y ordena los objetivos por nombre. Un valor de "kind" que no este en
KIND_CHOICES se ignora en vez de romper.

De paso, la barra de progreso pasa a usar goal.progress_state en lugar de
decidir el color en la plantilla con un if sobre el porcentaje. La logica ya
vivia en el modelo, que ademas distingue presupuestos (donde acercarse al
100% es un aviso) del resto; la plantilla del dashboard seguia con las clases
antiguas low/medium/high, que se retiran del CSS.

Incluye estado vacio y thead/tbody en la tabla, que le faltaban.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 16:16:58 +02:00
expenses_manager Anade filtro por tipo en objetivos y unifica la barra de progreso 2026-09-09 16:16:58 +02:00
.gitignore Added sqlite3 extension to ignore 2026-01-09 13:27:00 +01:00
LICENSE Initial commit 2026-01-07 16:39:32 +00:00
README.md Actualizar README.md 2026-07-29 11:20:39 +00:00

expenses_manager

Aplicación web de gestión de finanzas personales (gastos, ingresos, cuentas, categorías, objetivos y repostajes de vehículo), construida con Django y desplegada en un NAS Synology mediante Docker + PostgreSQL.

Características

  • Registro de gastos e ingresos, con categorías jerárquicas y etiquetas.
  • Cuentas con cálculo de saldo (soft-delete para preservar históricos).
  • Dashboard con gráficos por categoría, evolución de saldo y comparativas de periodo.
  • Objetivos de tres tipos: pago/deuda, presupuesto (mensual/anual) y ahorro.
  • Módulo de repostajes con cálculo de consumo, precio por litro y km recorridos.

Stack

  • Python 3.11 · Django 5.2
  • PostgreSQL (producción) / SQLite (desarrollo local por defecto)
  • Gunicorn + WhiteNoise
  • Docker (despliegue) · Jenkins (CI)

Desarrollo local

Por defecto, en local la aplicación usa SQLite, así que no necesitas levantar ninguna base de datos para empezar.

Requisitos

  • Python 3.11 (estos pasos asumen un entorno conda, pero sirve cualquier entorno virtual).

Pasos

  1. Clona el repositorio:

    git clone https://gitea.kuijper.es/jkuijperm/expenses_manager.git
    cd expenses_manager
    
  2. Crea y activa el entorno conda:

    conda create -n gastos python=3.11
    conda activate gastos
    
  3. Instala las dependencias:

    pip install -r expenses_manager/requirements.txt
    
  4. Crea el archivo .env (ver Variables de entorno). Para desarrollo basta con:

    DEBUG=True
    SECRET_KEY=cualquier-clave-para-desarrollo
    

    Con DEBUG=True y sin variables DB_*, se usa SQLite automáticamente.

  5. Aplica las migraciones y arranca el servidor:

    cd expenses_manager
    python manage.py migrate
    python manage.py runserver
    
  6. Abre http://127.0.0.1:8000/ en el navegador.

Datos de demostración (opcional): con DEBUG=True puedes poblar la base de datos con un usuario y datos de ejemplo:

python manage.py seed_demo

El comando está protegido para no ejecutarse si DEBUG=False.


Variables de entorno

La configuración se lee de un archivo .env (mediante python-dotenv) situado en expenses_manager/ (junto a manage.py). Este archivo no se versiona.

Variable Obligatoria Por defecto Descripción
SECRET_KEY Sí en producción Clave secreta de Django. Con DEBUG=False es obligatoria (si falta, la app no arranca).
DEBUG No False True en desarrollo. Activa SQLite por defecto y desactiva el hardening.
ALLOWED_HOSTS No localhost,127.0.0.1 Lista separada por comas.
CSRF_TRUSTED_ORIGINS No (vacío) Lista separada por comas (p. ej. https://midominio.com).
DB_ENGINE No sqlite3 postgresql para usar Postgres; cualquier otro valor usa SQLite.
DB_NAME Con Postgres Nombre de la base de datos.
DB_USER Con Postgres Usuario.
DB_PASSWORD Con Postgres Contraseña.
DB_HOST No localhost Host de la base de datos (db en Docker Compose).
DB_PORT No 5432 Puerto.

En el repositorio hay un archivo .env.example con estas variables como plantilla. Cópialo a .env y rellena los valores.


Despliegue con Docker

El despliegue en producción usa Docker con dos servicios: la aplicación Django (servida por Gunicorn) y una base de datos PostgreSQL.

Dockerfile

El Dockerfile está en el repositorio (app/Dockerfile en el árbol de despliegue) y hace lo esencial: parte de python:3.11-slim, instala las dependencias de requirements.txt y copia el código. A grandes rasgos:

FROM python:3.11-slim

ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1

WORKDIR /app/expenses_manager

COPY expenses_manager/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

docker-compose (no versionado)

El docker-compose.yml no está en el repositorio: es específico de la infraestructura del NAS y vive fuera del proyecto. A continuación se documenta qué debe contener, para poder reproducirlo. Ningún secreto va escrito en el archivo: todos los valores sensibles se leen del .env.

services:
  db:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - ./postgres:/var/lib/postgresql/data

  web:
    build: ./app
    container_name: finanzas_web
    command: gunicorn expenses_manager.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - ./app:/app
    ports:
      - "8001:8000"
    depends_on:
      - db
    env_file:
      - ./app/expenses_manager/.env

Notas:

  • Las credenciales de Postgres (DB_NAME, DB_USER, DB_PASSWORD) las toma Docker Compose de un .env situado junto al docker-compose.yml. Es un archivo distinto del .env de Django (que va dentro del proyecto y lo carga la propia app vía env_file).
  • El servicio web no repite las variables de base de datos en un bloque environment: las hereda del .env de Django a través de env_file.

Puesta en marcha y actualizaciones

Desde el directorio que contiene el docker-compose.yml:

git -C app pull                      # traer los últimos cambios al repo montado
docker-compose down
docker-compose up -d --build
docker-compose exec web python manage.py migrate
docker-compose exec web python manage.py collectstatic --noinput
  • migrate solo es necesario si hay migraciones nuevas.
  • collectstatic solo si han cambiado archivos estáticos (CSS/JS).
  • No ejecutes makemigrations en producción: las migraciones se generan en desarrollo y llegan versionadas con el git pull.

Tests

La suite usa pytest + pytest-django:

cd expenses_manager
pytest

La integración continua (Jenkins) ejecuta los tests en cada cambio de la rama main.


Ramas

  • main — solo recibe cambios ya probados (vía merge desde dev).
  • dev — rama de trabajo activa.