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-backendpnpm installCrea 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=tu-email@gmail.com
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 startEl 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 resetEl seed crea un usuario administrador por defecto:
- Email:
mail@sofi.dev - 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 --buildSolució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": "admin@mail.com", "password": "password" }Respuesta: setea cookie token + { "msg": "Login exitoso" }.
Body POST /resend-verification:
{ "email": "user@mail.com" }| 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