diff --git a/README.md b/README.md index 309dd41..ec4146d 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,215 @@ # expenses_manager -## Descripción -expenses_manager es una aplicación diseñada para ayudarte a gestionar tus gastos diarios. Fue creada con la intención de hacer que el seguimiento de finanzas personales sea más sencillo y eficiente. +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**. -## Uso Básico -La aplicación permite: -- Registrar ingresos y egresos. -- Visualizar tus gastos por categoría. -- Generar informes financieros mensuales y semanales. +## Características -## Índice -1. [Instalación](#instalación) -2. [Configuración](#configuración) -3. [Uso](#uso) +- 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. -## Instalación +## Stack -### Despliegue en Local +- Python 3.11 · Django 5.2 +- PostgreSQL (producción) / SQLite (desarrollo local por defecto) +- Gunicorn + WhiteNoise +- Docker (despliegue) · Jenkins (CI) -#### Requisitos: -- Python 3.8 o superior. -- pip. +--- -#### Pasos: -1. Clona el repositorio usando Git: +## Desarrollo local -```sh -git clone https://gitea.kuijper.es/jkuijperm/expenses_manager.git +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: + + ```sh + git clone https://gitea.kuijper.es/jkuijperm/expenses_manager.git + cd expenses_manager + ``` + +2. Crea y activa el entorno conda: + + ```sh + conda create -n gastos python=3.11 + conda activate gastos + ``` + +3. Instala las dependencias: + + ```sh + pip install -r expenses_manager/requirements.txt + ``` + +4. Crea el archivo `.env` (ver [Variables de entorno](#variables-de-entorno)). + Para desarrollo basta con: + + ```env + 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: + + ```sh + 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: +> +> ```sh +> 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: + +```dockerfile +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 ``` -2. Navega al directorio del proyecto: +### 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`. + +```yaml +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`: + +```sh +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`: ```sh cd expenses_manager +pytest ``` -3. Instala las dependencias necesarias: +La integración continua (Jenkins) ejecuta los tests en cada cambio de la rama +`main`. -```sh -pip install -r requirements.txt -``` +--- -### Despliegue en Docker +## Ramas -#### Pasos: -1. Clona el repositorio usando Git: - -```sh -git clone https://gitea.kuijper.es/jkuijperm/expenses_manager.git -``` - -2. Navega al directorio del proyecto: - -```sh -cd expenses_manager -``` - -3. Construye la imagen Docker: - -```sh -docker build -t expenses_manager . -``` - -4. Corre el contenedor: - -```sh -docker run -p 5000:5000 expenses_manager -``` - -## Configuración - -Después de clonar el repositorio y instalar las dependencias, puedes configurar la aplicación creando un archivo `.env` en el directorio raíz del proyecto con el siguiente contenido: - -env - -SECRET_KEY=mi_clave_secreta_única_y_segura - -DATABASE_URL=sqlite:///expenses.db # Otra URL de base de datos si es necesario - -## Uso - -1. Inicia la aplicación: - -```sh -python app.py -``` - -2. Abre tu navegador y visita `http://localhost:5000` para acceder a la interfaz de usuario. - -### Registro de Gastos -- Accede a la página de gastos y agrega nuevos registros manualmente o importa datos desde otras fuentes. \ No newline at end of file +- **`main`** — solo recibe cambios ya probados (vía merge desde `dev`). +- **`dev`** — rama de trabajo activa. \ No newline at end of file