Skip to content

Latest commit

 

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sistema SCM - Huevos Kikes

Huevos Kikes SCM es un sistema de gestión de cadena de suministro para negocios de distribución de huevos, construido con Django. Centraliza proveedores, clientes, inventario, ventas y compras en una sola aplicación, con caja en tiempo real, control de concurrencia a nivel de base de datos y una capa de seguridad y permisos pensada para un entorno de producción real, no solo para una demo.

Este README documenta la versión 2.1; las notas de versiones anteriores se conservan más abajo como referencia.

Capturas de pantalla

Login Dashboard
Login Dashboard
Detalle de venta Registro de venta
Detalle de venta Formulario de venta

Funcionalidades principales

  • Autenticación con captcha, throttling contra intentos de fuerza bruta en el login, y recuperación de contraseña por email HTML.
  • Proveedores: carga de RUT y Cámara de Comercio, CRUD completo; la eliminación queda restringida a usuarios staff.
  • Clientes: geolocalización con Google Maps mediante captura de latitud/longitud; la eliminación queda restringida a usuarios staff.
  • Inventario: tipos de huevo (A, AA, AAA) con control de stock y edición de precio/stock dentro de la propia aplicación.
  • Ventas: formsets dinámicos, autocompletado de precio por tipo de huevo, validación de stock con bloqueo de fila a nivel de base de datos, generación de factura en PDF, registro automático en caja, exportación a CSV/XLSX/PDF, filtros y totales. Editar una venta reconcilia stock y caja automáticamente.
  • Compras: validación de saldo de caja con bloqueo de fila, actualización de stock, registro automático en caja, exportación a CSV/XLSX/PDF, filtros y totales. Editar una compra reconcilia stock y caja automáticamente.
  • Dashboard: saldo actual de caja, totales de ingresos/egresos/neto, últimos movimientos, filtros de rango y gráfico de los últimos 30 días.
  • Integridad de datos: señales que revierten stock y caja al eliminar ventas o compras; una restricción de base de datos (CheckConstraint) impide que el stock quede negativo.

Resumen por versiones

Versión 2.1 (actual)

  • Seguridad: la factura en PDF requiere autenticación (antes era accesible sin login, enumerable por id); DEBUG pasa a False por defecto en lugar de fallar abierto; SECRET_KEY deja de tener un valor de reserva inseguro en producción; permisos por rol (is_staff) para eliminar, editar y exportar; throttling básico de login contra fuerza bruta.
  • Integridad de datos: bloqueo de filas (select_for_update) sobre stock y caja para evitar condiciones de carrera en ventas y compras concurrentes; editar una venta o compra reconcilia stock y caja (antes solo ocurría al eliminar una línea); restricción de base de datos contra stock negativo; corrección de una señal de limpieza de caja (pre_delete en lugar de post_delete) que dejaba transacciones huérfanas al eliminar ventas o compras.
  • Interfaz: corrección de referencias de plantilla a atributos inexistentes que dejaban fechas en blanco; formato de moneda consistente en toda la aplicación (separador de miles, sin decimales ficticios); indicador de sección activa en el menú lateral; ocultamiento de acciones no autorizadas según el rol del usuario en lugar de responder con un error 403; edición de inventario disponible dentro de la aplicación en lugar de requerir el panel de administración.
  • Despliegue: carga efectiva de variables de entorno en desarrollo mediante python-dotenv; separación de build.sh y start.sh, de forma que las migraciones se ejecutan al arrancar el servicio en lugar de durante el paso de build de Render, que no tiene acceso a la red privada donde vive la base de datos.

Versión 2.0

  • Seguridad: captcha en login, orígenes de confianza CSRF parametrizables, HSTS y encabezado de proxy SSL en producción.
  • Autenticación y recuperación: restablecimiento de contraseña por email HTML, con SMTP y respaldo a consola.
  • Listados: búsqueda, paginación y filtros por fecha en ventas y compras, con totales filtrados y exportación a CSV/Excel/PDF.
  • Dashboard: filtros rápidos de rango (hoy/7 días/30 días/mes o fechas personalizadas), totales de ingreso/egreso/neto y gráfico de 30 días con Chart.js.
  • Integridad de datos: señales que revierten stock y caja al eliminar transacciones.
  • Infraestructura: WhiteNoise en producción, configuración dinámica de email y base de datos, lista para Render.

Versión 1.0

  • CRUD de proveedores, clientes (con geolocalización), inventario, ventas y compras.
  • Validación de stock en ventas y de saldo de caja en compras, con registro automático en caja y factura en PDF por venta.
  • Exportación básica a Excel en inventario y factura en PDF de ventas.
  • Configuración funcional de Dockerfile, docker-compose y despliegue en Render.

Stack

  • Python 3.10+ (probado también en 3.12 y 3.13)
  • Django 4.2.x
  • PostgreSQL en producción, SQLite en desarrollo
  • Gunicorn y WhiteNoise para archivos estáticos
  • Despliegue en Render, con soporte tanto para runtime nativo de Python como para Docker

Requisitos (local)

  • Windows, macOS o Linux con Python 3.10+
  • Git
  • PostgreSQL opcional (SQLite por defecto)

Puesta en marcha local (PowerShell)

  1. Clonar el repositorio y crear el entorno
git clone <url-del-repositorio>
cd huevos-kikes
python -m venv venv
./venv/Scripts/Activate.ps1
  1. Instalar dependencias
pip install -r requirements.txt
  1. Configurar variables de entorno
copy .env.example .env

.env se carga automáticamente mediante python-dotenv. Valores mínimos para desarrollo:

SECRET_KEY=tu-secret-key
DEBUG=True
# DATABASE_URL=postgresql://usuario:password@localhost:5432/huevos_kikes_db
GOOGLE_MAPS_API_KEY=tu-api-key
# EMAIL_HOST_USER=...
# EMAIL_HOST_PASSWORD=...
# CSRF_TRUSTED_ORIGINS=https://tu-dominio.com

DEBUG es False por defecto y falla cerrado si la variable no está definida, por lo que DEBUG=True es obligatorio en desarrollo local; de lo contrario, la aplicación exige un SECRET_KEY real y rechaza hosts no listados. GOOGLE_MAPS_API_KEY es opcional: sin ella, el mapa del detalle de cliente no se muestra, sin afectar el resto de la aplicación.

  1. Migraciones y superusuario
python manage.py migrate
python manage.py createsuperuser

Los permisos de superusuario (is_staff) son necesarios para eliminar clientes o proveedores, editar ventas o compras existentes, exportar a CSV/XLSX/PDF y editar inventario. Un usuario autenticado sin ese permiso puede ver listados, crear ventas y compras, y crear o editar clientes y proveedores.

  1. Datos iniciales de inventario (opcional)
python manage.py shell -c "from inventario.models import TipoHuevo; TipoHuevo.objects.get_or_create(tipo='A', defaults={'precio_cubeta':25000,'stock_cubetas':0}); TipoHuevo.objects.get_or_create(tipo='AA', defaults={'precio_cubeta':30000,'stock_cubetas':0}); TipoHuevo.objects.get_or_create(tipo='AAA', defaults={'precio_cubeta':35000,'stock_cubetas':0})"
  1. Ejecutar el servidor de desarrollo
python manage.py runserver
  1. Ejecutar la suite de pruebas (opcional)
python manage.py test

Generación de PDF (WeasyPrint)

La factura y los reportes en PDF usan WeasyPrint, que depende de las librerías nativas de Cairo, Pango y GDK-Pixbuf. En Linux y en el despliegue por Docker se instalan mediante apt (ver Dockerfile); en Windows nativo requieren instalar por separado el runtime de GTK3. El resto de la aplicación funciona sin esta dependencia; su ausencia solo afecta a los botones de generación y exportación de PDF.

Producción en Render

La guía completa, paso a paso, está en DEPLOY_RENDER.md.

El proyecto se despliega como servicio de Python nativo (no Docker), con build.sh y start.sh como pasos separados:

Campo Valor
Build Command pip install --upgrade pip && pip install -r requirements.txt && bash build.sh
Start Command bash start.sh

build.sh solo ejecuta collectstatic y no requiere acceso a la base de datos. Las migraciones y la creación del superusuario están en start.sh, que corre al arrancar el servicio: el Build Command de Render no tiene acceso a la red privada donde vive la base de datos, de modo que ejecutar migrate en ese paso falla siempre con un error de resolución de DNS, independientemente de la configuración de DATABASE_URL.

El repositorio también incluye un Dockerfile con su propio entrypoint.sh equivalente, para despliegues con runtime Docker en lugar de Python nativo.

Variables de entorno (Web Service)

Requeridas:

SECRET_KEY=<segura, generada aparte; la aplicación no arranca sin esto cuando DEBUG=False>
DATABASE_URL=<Internal Database URL de Postgres, en la misma región que el Web Service>

DEBUG no requiere definirse: su valor por defecto (False) es el correcto en producción.

ALLOWED_HOSTS y CSRF_TRUSTED_ORIGINS tampoco suelen requerir configuración manual: settings.py agrega automáticamente el hostname que Render inyecta (RENDER_EXTERNAL_HOSTNAME) a ambos cuando DEBUG=False. Solo son necesarios al usar un dominio propio además de *.onrender.com.

Opcionales:

GOOGLE_MAPS_API_KEY=<api-key>              # sin esta variable, el mapa no se muestra
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@tu-dominio.com
DJANGO_SUPERUSER_PASSWORD=<segura>         # start.sh crea o actualiza este usuario en cada arranque
COMPANY_NAME=Huevos Kikes                  # datos de la empresa en la factura PDF
COMPANY_NIT=...
COMPANY_ADDRESS=...
COMPANY_PHONE=...
COMPANY_EMAIL=...
EMAIL_HOST_USER=...                        # envío real de correo (App Password de Gmail)
EMAIL_HOST_PASSWORD=...

Consideraciones de despliegue

  • Región de la base de datos: el hostname interno de Postgres solo resuelve entre servicios de la misma región en Render. Un Web Service y una base de datos en regiones distintas producen el mismo error de DNS que un Build Command mal configurado.
  • Expiración del plan gratuito de Postgres: la base de datos se elimina automáticamente a los 90 días. Un error could not translate host name ... to address después de un período de funcionamiento normal suele indicar esto; la solución es crear una base de datos nueva, actualizar DATABASE_URL con su Internal Database URL, y recrear los datos semilla, que no se conservan.
  • Instalación de dependencias: Render no instala requirements.txt automáticamente en el runtime nativo de Python; debe ser un paso explícito dentro del propio Build Command.

Google Maps

  • La clave se inyecta a través de un context processor (settings.GOOGLE_MAPS_API_KEY).
  • Se recomienda restringirla por HTTP referrer en Google Cloud Console: https://huevos-kikes.onrender.com/*.
  • APIs sugeridas: Maps JavaScript API y Geocoding API.
  • Sin la variable configurada, el mapa del detalle de cliente no se muestra; el resto de la aplicación no se ve afectado.

Integridad de datos (señales)

  • transacciones/signals.py revierte stock y caja al eliminar ventas o compras, mediante un receptor pre_delete que corre antes de que el SET_NULL de la relación con caja limpie la referencia.
  • Editar una venta o compra (agregar, quitar o modificar cantidad/tipo de una línea) también reconcilia stock y el monto en caja, bloqueando las filas afectadas (select_for_update) para evitar condiciones de carrera con operaciones concurrentes.

Permisos

  • Cualquier usuario autenticado: ver listados y detalles, crear ventas y compras, crear y editar clientes y proveedores.
  • Solo usuarios con is_staff: eliminar clientes o proveedores, editar ventas o compras existentes, exportar a CSV/XLSX/PDF, editar inventario.

Estructura

huevos-kikes/
├─ core/
├─ proveedores/
├─ clientes/
├─ inventario/
├─ transacciones/
├─ templates/
├─ static/
├─ staticfiles/
├─ media/
├─ docs/screenshots/
├─ huevos_kikes_scm/
├─ Dockerfile          # despliegue alternativo vía Docker
├─ build.sh            # Build Command en Render (collectstatic)
├─ start.sh            # Start Command en Render (migrate, superusuario, gunicorn)
├─ requirements.txt
└─ manage.py

Solución de problemas

  • could not translate host name "dpg-..." to address: si ocurre durante el build, migrate se está ejecutando en el Build Command, que no tiene acceso a la red privada; debe moverse al Start Command (start.sh). Si ocurre durante el arranque del servicio, la base de datos probablemente fue eliminada (expiración del plan gratuito) o está en una región distinta a la del Web Service.
  • ModuleNotFoundError: No module named 'django' en el build: el Build Command no incluye pip install -r requirements.txt de forma explícita.
  • DisallowedHost: si ALLOWED_HOSTS se definió manualmente, debe ser el hostname sin el prefijo https:// (ese prefijo corresponde a CSRF_TRUSTED_ORIGINS). Si no se definió, verificar que DEBUG=False, ya que la detección automática del host de Render solo se aplica en ese caso.
  • relation ... does not exist: indica migraciones pendientes; verificar que start.sh (no build.sh) sea el Start Command, y que su log muestre "Running Database Migrations..." antes de iniciar Gunicorn.
  • Panel de administración sin estilos o error 500 de manifiesto de estáticos: verificar que collectstatic se ejecute (build.sh).
  • Envío de correo en desarrollo: sin credenciales se usa el backend de consola; con EMAIL_HOST_USER/EMAIL_HOST_PASSWORD (App Password de Gmail) se usa SMTP real.
  • Captcha no funciona: verificar que captcha esté en INSTALLED_APPS y correctamente migrado.
  • PDF no se genera en Windows local: requiere el runtime de GTK3 (ver sección de WeasyPrint).

Licencia y créditos

Proyecto académico — UNIMINUTO, Sistemas de Información.

About

Supply chain management system for an egg distribution business, built with Django and PostgreSQL. Real-time inventory, sales, purchases, and cash tracking, with production-grade security and role-based permissions.

Topics

Resources

Code of conduct

Contributing

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages