API REST para sistema integral de gestión de tiendas, recursos humanos, inventario y ventas, construida con Node.js, Express, TypeScript y Prisma ORM con SQLite.
- Características
- Tecnologías
- Arquitectura del Proyecto
- Requisitos Previos
- Instalación
- Configuración
- Scripts Disponibles
- Base de Datos
- Docker
- Funcionalidades
- API Endpoints
- Desarrollo
- Licencia
- Autenticación y Autorización con JWT
- Gestión de Recursos Humanos (empleados, nóminas, asistencias, permisos)
- Control de Inventario (productos, almacenes, transferencias, logs de stock)
- Sistema de Ventas (ventas, pagos, devoluciones, descuentos)
- Gestión de Turnos con sistema de intercambio entre empleados
- Reportes y Métricas de desempeño
- Dockerizado para fácil deployment (incluye Base de Datos y Prisma Studio integrados)
- Seguridad y Encriptación con
bcrypt,jsonwebtoken(en cookies HttpOnly) y tokens CSRF - Subida de Imágenes a Cloudinary para avatares de empleados
- Validación de datos con express-validator
- Node.js 22 - Runtime de JavaScript
- TypeScript 5.9 - Tipado estático
- Express 5.2 - Framework web
- Prisma 7.3 - ORM y query builder
- SQLite con better-sqlite3
- Prisma Client con soporte para adaptador SQLite
- bcrypt - Hash de contraseñas
- jsonwebtoken - Tokens JWT para autenticación
- cors - Control de acceso cross-origin
- nodemon - Hot reload en desarrollo
- ts-node - Ejecución de TypeScript
- tsx - Ejecución rápida de TypeScript
- pnpm - Gestor de paquetes eficiente
store-system-backend/
├── prisma/
│ ├── schema/ # Esquemas Prisma modulares
│ │ ├── auth.prisma # Autenticación y usuarios
│ │ ├── base.prisma # Configuración base
│ │ ├── hr.prisma # Recursos humanos
│ │ ├── inventory.prisma # Inventario
│ │ └── sales.prisma # Ventas
│ ├── migrations/ # Historial de migraciones
│ ├── seed.ts # Datos iniciales
│ └── src/
│ └── index.ts # Cliente Prisma extendido
├── src/
│ ├── config/ # Configuraciones
│ │ ├── db.config.ts
│ │ ├── envs.config.ts
│ │ └── prisma.ts
│ ├── controller/ # Controladores
│ ├── service/ # Lógica de negocio
│ ├── router/ # Rutas
│ ├── middlewares/ # Middlewares personalizados
│ ├── helpers/ # Utilidades
│ ├── model/ # Modelos de servidor
│ └── app.ts # Punto de entrada
├── docker-compose.yml # Orquestación Docker
├── Dockerfile # Imagen Docker
├── prisma.config.ts # Configuración Prisma
└── package.json
- Node.js >= 22.x
- pnpm >= 10.28.2 (instalado automáticamente con corepack)
- Docker y Docker Compose (opcional, para deployment)
git clone <repository-url> cd store-system-backend
pnpm install
Crea un archivo .env en la raíz del proyecto:
# Server PORT=8080 NODE_ENV=development # Database DATABASE_URL="file:/app/data/dev.db" # Si corres localmente "file:./dev.db" # JWT JWT_SECRET_KEY=your-super-secret-key-change-this # Cloudinary (Imágenes) CLOUDINARY_CLOUD_NAME=tu-cloud-name CLOUDINARY_API_KEY=tu-api-key CLOUDINARY_API_SECRET=tu-api-secret # Nodemailer (Correos) EMAIL_USER=[email protected] EMAIL_PASS=tu-password-de-app
# Generar el cliente Prisma pnpm db:generate # Ejecutar migraciones pnpm db:migrate # Sembrar datos iniciales (admin por defecto) pnpm db:seed
# Desarrollo (con hot reload) pnpm dev # Producción pnpm build pnpm start
El servidor estará disponible en http://localhost:8080
El proyecto utiliza un cliente Prisma extendido que automáticamente:
- Hashea contraseñas en operaciones
create,updateyupsert - Usa bcrypt con salt rounds de 10
- Mantiene el patrón singleton en desarrollo
Ubicación: prisma/src/index.ts
# Desarrollo pnpm dev # Inicia servidor con nodemon (hot reload) # Compilación pnpm build # Compila TypeScript a JavaScript pnpm start # Ejecuta servidor compilado # Base de datos pnpm db:generate # Genera Prisma Client pnpm db:migrate # Ejecuta migraciones pnpm db:studio # Abre Prisma Studio (GUI) pnpm db:seed # Siembra datos iniciales # Utilidades pnpm clean # Limpia carpeta dist/
El proyecto utiliza múltiples archivos de schema Prisma para mejor organización:
User- Usuarios del sistema con roles y verificación
Employee- Información de empleadosSchedule- Horarios de trabajoTimeOff- Días libres y vacacionesAttendanceLog- Registro de asistenciasPayroll- NóminasSalaryLog- Historial de salariosPerformanceWarning- Advertencias de desempeñoShiftSwap- Intercambios de turnos
Warehouse- AlmacenesProduct- ProductosStockLog- Movimientos de inventarioTransfer- Transferencias entre almacenesTransferItem- Ítems de transferencia
Sale- Ventas realizadasSaleItem- Productos vendidosPayment- PagosRefund- DevolucionesDiscount- Descuentos aplicados
# Crear nueva migración pnpm db:migrate # Ver estado de migraciones pnpm exec prisma migrate status # Resetear base de datos (CUIDADO: solo en desarrollo) pnpm exec prisma migrate reset
El seed crea un usuario administrador por defecto:
- Email:
[email protected] - Password:
sofievO - Role: Admin
- Status: Activo y Verificado
# Construir imagen docker compose build # Iniciar contenedor docker compose up -d # Ver logs docker compose logs -f app # Detener docker compose down
- Multi-stage build para optimizar tamaño
- Instalación de dependencias con frozen lockfile
- Generación automática de Prisma Client
- Volumen persistente para base de datos SQLite
- Migraciones automáticas al iniciar
- Política de restart para alta disponibilidad
Los datos se persisten en ./data/prod.db en el host.
Si al iniciar sesión obtienes un error de usuario no encontrado, es probable que la base de datos dentro del contenedor (data/dev.db) no tenga los datos iniciales.
Solución Automática:
El proyecto está configurado para ejecutar pnpm db:seed automáticamente al iniciar el contenedor en modo desarrollo.
Si tienes este problema, reconstruye el contenedor:
docker-compose down docker-compose up --build
Solución Manual: Si prefieres sincronizar tu base de datos local con la de Docker manualmente:
# Copiar tu DB local a la carpeta data (usada por Docker) sudo cp dev.db data/dev.db # Ajustar permisos (Docker crea archivos como root) sudo chown $(whoami):$(whoami) data/dev.db
- Registro y gestión de usuarios
- Registro y gestión de empleados
- Modificación de permisos
- Actualización de datos personales
- Registro de días libres
- Gestión de nóminas
- Control de inventario
- Aprobación de intercambios de turnos
- Acceso a perfil personal
- Consulta de días libres disponibles
- Consulta de horas extra
- Visualización de horarios
- Descarga de recibos de nómina
- Solicitud de intercambio de turnos
- Registro de ventas
Base URL:
http://localhost:3000Auth: CookiehttpOnly(token) generada al hacer login. CSRF: Los métodosPOST,PUT,DELETEyPATCHrequieren el headerX-CSRF-Token.
- Al montar la app, llamar
GET /api/v1/security/csrf-tokenpara obtener el token CSRF. - Incluir ese token en el header
X-CSRF-Tokenen todas las mutaciones. - Todas las peticiones deben enviarse con
credentials: 'include'para que la cookie funcione.
| Método | Ruta | Descripción | Auth |
|---|---|---|---|
GET |
/api/v1/security/csrf-token |
Obtener token CSRF | Pública |
| Método | Ruta | Descripción | Auth |
|---|---|---|---|
POST |
/api/v1/auth/login |
Inicio de sesión | Pública |
GET |
/api/v1/auth/verify-email?token= |
Verificar email vía link | Pública |
POST |
/api/v1/auth/resend-verification |
Reenviar correo de verificación | Pública |
POST |
/api/v1/auth/logout |
Cerrar sesión | JWT cookie |
Body POST /login:
{ "email": "[email protected]", "password": "password" }Respuesta: setea cookie token + { "msg": "Login exitoso" }.
Body POST /resend-verification:
{ "email": "[email protected]" }| Método | Ruta | Descripción | Auth |
|---|---|---|---|
GET |
/api/v1/profile |
Obtener perfil del usuario logueado | JWT cookie |
Todos los endpoints de este módulo requieren JWT + rol ADMIN.
| Método | Ruta | Descripción | Auth |
|---|---|---|---|
GET |
/api/v1/employees |
Listar todos los empleados | JWT + ADMIN |
POST |
/api/v1/employees |
Crear empleado (multipart/form-data) | JWT + ADMIN |
GET |
/api/v1/employees/:id |
Obtener empleado por ID | JWT + ADMIN |
PUT |
/api/v1/employees/:id |
Actualizar datos de empleado | JWT + ADMIN |
Campos POST /employees (multipart/form-data):
| Campo | Tipo | Requerido |
|---|---|---|
role |
string | Sí |
name |
string | Sí |
lastname |
string | Sí |
email |
Sí | |
birthdate |
date | Sí |
rfc |
string | Sí |
nss |
string | Sí |
phone |
string | Sí |
address |
string | Sí |
salary |
number | Sí |
profileImage |
file | No (opcional) |
Al crear un empleado se genera un password temporal y se envía un correo de verificación automáticamente. La imagen se sube a Cloudinary.
| Módulo | Endpoints listos | Pendientes |
|---|---|---|
| Security | 1 | — |
| Auth | 4 | — |
| Profile | 1 | Editar perfil propio |
| Employees | 4 | DELETE, filtros, paginación |
| Inventario | 0 | No iniciado |
| Ventas | 0 | No iniciado |
El desarrollo sigue un plan estructurado. Para ver los próximos pasos consulta:
- Arquitectura: MVC (Model-View-Controller)
- Estilo: camelCase para variables y funciones
- Imports: Absolutos desde
src/ - Tipos: TypeScript strict mode
- Crear schema en
prisma/schema/ - Ejecutar migración:
pnpm db:migrate - Crear controlador en
src/controller/ - Crear servicio en
src/service/ - Crear router en
src/router/ - Registrar router en
src/model/server.ts
El proyecto usa ts-node con nodemon para hot reload:
// nodemon.json { "watch": ["src", "prisma"], "ext": "ts,prisma", "exec": "ts-node src/app.ts" }
- El script de seed está bloqueado en producción (
NODE_ENV === 'production') - Cambia
JWT_SECRET_KEYen producción — el.envactual tiene un valor débil - SQLite es ideal para desarrollo; considera PostgreSQL/MySQL para producción
- Los logs de queries solo aparecen en desarrollo (configurado en
prisma/src/index.ts)
MIT License - Ver archivo LICENSE para más detalles
Desarrollado por el equipo de Store System