Sistema de Control de Stock — Guía Técnica
Manual del Administrador
Guía completa de administración del sistema de control de stock
Manual del Administrador
Visión general de los componentes técnicos, tecnologías utilizadas y estructura del proyecto.
El sistema de Control de Stock de ACyEDE utiliza una arquitectura cliente-servidor de tres capas. El frontend es una aplicación de página única (SPA) construida con React que se ejecuta en el navegador del usuario. El backend es una API REST construida con Node.js y Express que gestiona la lógica de negocio y la autenticación. La base de datos es un archivo SQLite gestionado con la librería better-sqlite3.
Esta arquitectura permite que el sistema funcione en un único servidor, sin necesidad de instalar un motor de base de datos externo. Toda la información se almacena en un solo archivo .db, lo que simplifica enormemente el backup y la portabilidad.
| Componente | Tecnología | Versión | Propósito |
|---|---|---|---|
| Frontend | React + Vite | 19.x / 6.x | Interfaz de usuario SPA, compilación rápida |
| Backend | Node.js + Express | 22.x / 4.x | API REST, lógica de negocio |
| Base de datos | SQLite (better-sqlite3) | 3.x / 11.x | Almacenamiento persistente en archivo |
| Autenticación | JWT + bcrypt | — | Tokens de sesión, hash de contraseñas |
| Gráficos | Chart.js | 4.x | Visualización de datos en dashboard |
| Exportación | SheetJS (xlsx) | — | Exportación a Excel y CSV |
| Upload de archivos | Multer | — | Subida de fotos de productos |
stock.db), lo que simplifica enormemente las tareas de backup y migración.
Manual del Administrador
Requisitos previos, pasos de instalación, variables de entorno y configuración inicial del sistema.
| Requisito | Mínimo | Recomendado | Notas |
|---|---|---|---|
| Node.js | 18.x LTS | 22.x LTS | Descargar de nodejs.org |
| npm | 9.x | 10.x | Incluido con Node.js |
| Sistema operativo | Windows 10+, Linux, macOS | Cualquier SO con soporte para Node.js | |
| RAM | 1 GB | 2 GB+ | Para el servidor en producción |
| Disco | 500 MB | 2 GB+ | Depende del volumen de fotos |
Cloná el repositorio o copiá la carpeta del proyecto al servidor:
# Opción A: Clonar desde repositorio git clone https://github.com/tu-org/acyede-stock.git cd acyede-stock # Opción B: Copiar carpeta manualmente # Copiar la carpeta completa al servidor y navegar a ella
Ejecutá el comando de instalación unificado desde la raíz del proyecto:
npm run install:all # Este comando instala las dependencias de: # - Raíz del proyecto (scripts de gestión) # - server/ (API backend + SQLite) # - client/ (React frontend)
Creá o editá el archivo server/.env con la configuración necesaria:
# Puerto del servidor PORT=3001 # Clave secreta para firmar tokens JWT # ¡CAMBIÁ ESTO EN PRODUCCIÓN! JWT_SECRET=tu_clave_secreta_super_segura_aqui # Ruta al archivo de base de datos DB_PATH=./db/stock.db
Para desarrollo local con hot-reload:
npm run dev # Esto inicia simultáneamente: # - Backend en http://localhost:3001 # - Frontend en http://localhost:5173 (con proxy al backend)
Para despliegue en producción, compilá el frontend y luego iniciá el servidor:
# Compilar el frontend para producción npm run build # Iniciar el servidor (sirve el frontend compilado + API) npm start # El sistema completo queda disponible en: # http://localhost:3001
JWT_SECRET por defecto en producción. Generá una clave aleatoria segura de al menos 64 caracteres. Podés usar: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
| Variable | Valor por Defecto | Obligatoria | Descripción |
|---|---|---|---|
PORT |
3001 |
No | Puerto en el que escucha el servidor HTTP. Cambiá este valor si el puerto 3001 está ocupado por otra aplicación. |
JWT_SECRET |
(auto-generado) |
Sí (prod) | Clave secreta para firmar y verificar los tokens JWT de autenticación. Si no se define, el sistema genera una automáticamente (cambia en cada reinicio, cerrando todas las sesiones). |
DB_PATH |
./db/stock.db |
No | Ruta al archivo de base de datos SQLite. Relativa a la carpeta server/. El directorio debe existir; el archivo se crea automáticamente si no existe. |
Después de iniciar el sistema, verificá que todo funcione correctamente:
# Verificar que el servidor responde curl http://localhost:3001/api/auth/me # Respuesta esperada (sin token): {"error":"Token no proporcionado"} # Esto confirma que la API está funcionando correctamente # Probar login curl -X POST http://localhost:3001/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin123"}' # Respuesta esperada: {"token":"eyJ...", "user":{...}}
Manual del Administrador
Usuarios predeterminados, creación y administración de cuentas, roles y permisos del sistema.
Al ejecutar el sistema por primera vez, se crean automáticamente tres usuarios con roles distintos. Estos usuarios permiten el acceso inicial al sistema y deben ser modificados inmediatamente después del primer inicio de sesión.
| Usuario | Contraseña | Rol | Descripción |
|---|---|---|---|
admin |
admin123 |
Administrador | Acceso completo a todos los módulos y configuraciones |
operador |
operador123 |
Operador | Puede gestionar productos, movimientos y ver reportes |
consulta |
consulta123 |
Solo lectura | Solo puede consultar información, sin modificar datos |
Solo los usuarios con rol Administrador pueden crear nuevas cuentas.
Navegá a la sección Usuarios desde el menú lateral (escritorio) o desde la navegación inferior (móvil).
Hacé clic en el botón "Nuevo Usuario" ubicado en la parte superior de la página.
Ingresá los datos del nuevo usuario:
Hacé clic en "Guardar". El usuario podrá iniciar sesión de inmediato con las credenciales asignadas.
Desde la lista de usuarios, hacé clic en el botón de edición (ícono de lápiz) junto al usuario que querés modificar. Podés cambiar:
Los usuarios no se eliminan del sistema, sino que se desactivan (soft-disable). Un usuario desactivado no puede iniciar sesión, pero su historial de movimientos se conserva para auditoría. Los usuarios desactivados pueden ser reactivados en cualquier momento por un administrador.
| Funcionalidad | Administrador | Operador | Solo Lectura |
|---|---|---|---|
| Ver dashboard y KPIs | ✔ Sí | ✔ Sí | ✔ Sí |
| Ver catálogo de productos | ✔ Sí | ✔ Sí | ✔ Sí |
| Crear / editar productos | ✔ Sí | ✔ Sí | ✘ No |
| Eliminar / desactivar productos | ✔ Sí | ✘ No | ✘ No |
| Registrar movimientos de stock | ✔ Sí | ✔ Sí | ✘ No |
| Ver historial de movimientos | ✔ Sí | ✔ Sí | ✔ Sí |
| Ver y exportar reportes | ✔ Sí | ✔ Sí | ✔ Sí |
| Gestionar categorías | ✔ Sí | ✔ Sí | ✘ No |
| Gestionar proveedores | ✔ Sí | ✔ Sí | ✘ No |
| Gestionar usuarios | ✔ Sí | ✘ No | ✘ No |
Manual del Administrador
Estructura de la base de datos SQLite, esquema de tablas, relaciones entre entidades y mecanismo de auto-seeding.
La base de datos es un archivo SQLite ubicado en:
server/db/stock.db
Este archivo contiene toda la información del sistema: usuarios, productos, categorías, proveedores y movimientos de stock. Al ser un único archivo, es extremadamente fácil de respaldar, migrar o clonar.
La base de datos consta de 5 tablas principales:
| Tabla | Descripción | Campos Principales |
|---|---|---|
users |
Cuentas de usuario del sistema | id, username, password (hash bcrypt), fullName, role, active, createdAt |
categories |
Categorías de productos | id, name, description, active, createdAt |
suppliers |
Proveedores de productos | id, name, contact, phone, email, address, active, createdAt |
products |
Catálogo de productos | id, name, sku, description, categoryId, supplierId, stock, minStock, price, image, active, createdAt |
stock_movements |
Registro de entradas, salidas y ajustes | id, productId, type (entrada/salida/ajuste), quantity, reason, userId, createdAt |
Diagrama de Relaciones
La primera vez que se inicia el servidor, el sistema detecta que la base de datos está vacía y ejecuta automáticamente el proceso de seeding:
stock.db y reiniciás. El seeding se ejecutará nuevamente y se creará una base de datos limpia con los datos de ejemplo.
Manual del Administrador
Procedimientos de respaldo manual y automatizado, restauración de la base de datos y buenas prácticas de protección de datos.
stock.db con un editor externo mientras el servidor está corriendo puede causar corrupción de datos irrecuperable. Siempre detenés el servidor antes de manipular el archivo.
El backup del sistema consiste en respaldar dos elementos: la base de datos y las fotos de productos.
Asegurate de que el servidor no esté en ejecución para evitar inconsistencias. Si usás PM2: pm2 stop acyede-stock. Si ejecutás directamente: presioná Ctrl+C en la terminal.
Copiá el archivo server/db/stock.db a una ubicación segura:
copy server\db\stock.db D:\backups\stock_2026-07-07.db
Las fotos de productos se almacenan en server/uploads/. Respaldá esta carpeta completa:
xcopy server\uploads D:\backups\uploads_2026-07-07\ /E /I
Una vez completado el backup, reiniciá el servidor normalmente: npm start o pm2 start acyede-stock.
Usá el siguiente script de Windows (.bat) para automatizar el backup diario. Programalo en el Programador de Tareas de Windows para que se ejecute automáticamente.
@echo off REM ============================================ REM ACyEDE Stock - Script de Backup Automático REM Programar en el Programador de Tareas REM ============================================ REM Configuración - AJUSTAR ESTAS RUTAS SET PROJECT_DIR=C:\acyede-stock SET BACKUP_DIR=D:\backups\acyede SET MAX_BACKUPS=30 REM Generar marca de tiempo SET TIMESTAMP=%date:~6,4%-%date:~3,2%-%date:~0,2%_%time:~0,2%-%time:~3,2% SET TIMESTAMP=%TIMESTAMP: =0% REM Crear directorio de backup si no existe IF NOT EXIST "%BACKUP_DIR%" MKDIR "%BACKUP_DIR%" REM Copiar base de datos echo [%TIMESTAMP%] Iniciando backup... copy "%PROJECT_DIR%\server\db\stock.db" "%BACKUP_DIR%\stock_%TIMESTAMP%.db" REM Copiar carpeta de uploads xcopy "%PROJECT_DIR%\server\uploads" "%BACKUP_DIR%\uploads_%TIMESTAMP%\" /E /I /Q REM Registrar en log echo [%TIMESTAMP%] Backup completado exitosamente >> "%BACKUP_DIR%\backup_log.txt" echo Backup completado: %BACKUP_DIR%\stock_%TIMESTAMP%.db
taskschd.msc), creá una nueva tarea que ejecute este script diariamente (por ejemplo, a las 2:00 AM). Asegurate de que la tarea se ejecute incluso si el usuario no ha iniciado sesión.
Detenés el servidor para liberar el archivo de base de datos.
Reemplazá el archivo actual con la copia de backup:
# Renombrar el archivo actual (por seguridad) rename server\db\stock.db stock_corrupted.db # Copiar el backup copy D:\backups\acyede\stock_2026-07-05.db server\db\stock.db
Si también necesitás restaurar las fotos de productos:
xcopy D:\backups\acyede\uploads_2026-07-05\ server\uploads\ /E /I /Y
Iniciá el servidor normalmente. Verificá que los datos se hayan restaurado correctamente ingresando al sistema y revisando la información.
Manual del Administrador
Opciones de despliegue, configuración para producción, gestión de procesos y checklist de seguridad.
La opción más simple es ejecutar el sistema en una PC o servidor dedicado dentro de la red local de la organización. Los demás dispositivos acceden al sistema a través de la dirección IP del servidor.
Instalá Node.js en la PC/servidor que va a alojar el sistema. Asegurate de que tenga una IP fija en la red local (o configurá una IP estática en la red).
npm run install:all npm run build npm start
Los usuarios de la red acceden abriendo un navegador y visitando:
http://IP_DEL_SERVIDOR:3001 # Ejemplo: http://192.168.1.100:3001
Para que el servidor se mantenga ejecutando en segundo plano y se reinicie automáticamente ante errores o reinicios del sistema, usá PM2:
# Instalar PM2 globalmente npm install -g pm2 # Iniciar el servidor con PM2 pm2 start server/index.js --name "acyede-stock" # Configurar inicio automático con Windows pm2 save pm2-startup install # Comandos útiles de PM2 pm2 status # Ver estado del proceso pm2 logs acyede-stock # Ver logs en tiempo real pm2 restart acyede-stock # Reiniciar pm2 stop acyede-stock # Detener
pm2-windows-startup: npm install -g pm2-windows-startup y luego pm2-startup install. Esto registra PM2 como un servicio de Windows.
Para acceso desde internet (fuera de la red local), podés desplegar en un servicio de hosting en la nube.
| Servicio | Tipo | Costo | Notas |
|---|---|---|---|
| Railway | PaaS | Desde gratis | Deploy simple desde Git. Ideal para empezar. Nota: SQLite se pierde al redeployar (usar volumen persistente). |
| Render | PaaS | Desde gratis | Similar a Railway. Soporta discos persistentes en plan pago. |
| VPS (DigitalOcean, etc.) | IaaS | ~$5/mes | Control total. Requiere configuración manual de Node.js, PM2, Nginx y SSL. |
Subí el proyecto a un repositorio Git o usá el CLI del servicio elegido para deployar directamente.
Definí PORT, JWT_SECRET y DB_PATH en el panel de configuración del servicio.
Build command: npm run install:all && npm run build
Start command: npm start
Configurá un dominio personalizado y un certificado SSL en el panel del servicio de hosting.
Antes de poner el sistema en producción, verificá cada punto de esta lista:
node --version.
Manual del Administrador
Guía de diagnóstico y resolución de los problemas más comunes del sistema.
| Problema | Causa Probable | Solución |
|---|---|---|
| El servidor no arranca | El puerto configurado ya está en uso por otra aplicación | Cambiá el valor de PORT en server/.env a otro puerto disponible (ej: 3002, 8080). Verificá puertos en uso con: netstat -ano | findstr :3001 |
| Error de base de datos al iniciar | El archivo stock.db está corrupto o la carpeta db/ no existe |
Verificá que exista la carpeta server/db/. Si el archivo está corrupto, restaurá desde un backup (Sección 5.3) o eliminá el archivo para que se recree. |
| No puedo iniciar sesión | Contraseña incorrecta, usuario desactivado, o token JWT inválido | Verificá usuario y contraseña. Si olvidaste la contraseña de admin, otro administrador puede reseteártela. Como último recurso, eliminá stock.db para recrear los usuarios predeterminados (se pierden datos). |
| Las fotos de productos no se ven | La carpeta server/uploads/ no existe o no tiene permisos de lectura |
Creá la carpeta manualmente: mkdir server\uploads. Verificá que el servidor tenga permisos de lectura y escritura sobre esa carpeta. |
Error better-sqlite3 |
El módulo nativo no está compilado para tu versión de Node.js | Ejecutá: npm rebuild better-sqlite3 desde la carpeta server/. Si no funciona, eliminá node_modules y ejecutá npm install nuevamente. |
| El frontend no compila | Dependencias faltantes o versión incompatible de Node.js | Ejecutá npm install dentro de la carpeta client/. Verificá que tengas Node.js 18 o superior: node --version |
| Error CORS en el navegador | El frontend y backend están en orígenes diferentes sin proxy configurado | En desarrollo, verificá que vite.config.js tenga el proxy configurado hacia el backend. En producción, usá npm start que sirve el frontend desde el mismo servidor. |
| Sesiones se cierran al reiniciar | El JWT_SECRET no está fijo (se autogenera en cada inicio) |
Definí un JWT_SECRET fijo en server/.env. Así los tokens firmados siguen siendo válidos entre reinicios del servidor. |
| El sistema está lento | Base de datos muy grande, muchas fotos, o servidor con pocos recursos | Verificá el tamaño de stock.db. Considerá limpiar movimientos antiguos. Asegurate de que el servidor tenga al menos 2 GB de RAM disponibles. |
| No se puede acceder desde otro dispositivo | Firewall bloqueando el puerto, o dispositivo en otra red | Asegurate de que el firewall de Windows permita conexiones entrantes al puerto del servidor. Ambos dispositivos deben estar en la misma red local. |
# Verificar versión de Node.js (requiere 18+) node --version # Verificar versión de npm npm --version # Verificar si el puerto 3001 está en uso (Windows) netstat -ano | findstr :3001 # Ver procesos de Node.js en ejecución (Windows) tasklist | findstr node # Verificar tamaño de la base de datos (PowerShell) Get-Item server\db\stock.db | Select-Object Name, Length # Verificar contenido de la carpeta uploads dir server\uploads | Measure-Object # Ver logs de PM2 (si usás PM2) pm2 logs acyede-stock --lines 50 # Verificar que la API responde curl http://localhost:3001/api/auth/me
Si nada funciona, podés hacer un reinicio completo reinstalando las dependencias:
# 1. Detener cualquier proceso en ejecución pm2 stop all # o Ctrl+C si ejecutás directamente # 2. Eliminar dependencias rmdir /s /q node_modules rmdir /s /q server\node_modules rmdir /s /q client\node_modules # 3. Reinstalar todo npm run install:all # 4. Recompilar npm run build # 5. Reiniciar npm start
server/db/stock.db antes de cualquier operación de mantenimiento.
Manual del Administrador
Listado completo de endpoints de la API REST, métodos HTTP, parámetros y requisitos de autenticación.
Todos los endpoints devuelven respuestas en formato JSON. La autenticación se realiza mediante un token JWT que debe incluirse en el header Authorization: Bearer <token> de cada solicitud (excepto el login).
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| POST | /api/auth/login |
Iniciar sesión. Body: {"username", "password"}. Retorna token JWT. |
Público |
| GET | /api/auth/me |
Obtener datos del usuario autenticado actual. | Todos |
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| GET | /api/products |
Listar todos los productos activos. Soporta query params: ?search=, ?category= |
Todos |
| GET | /api/products/:id |
Obtener detalle de un producto por ID. | Todos |
| POST | /api/products |
Crear un nuevo producto. Soporta multipart/form-data para subir foto. |
Admin / Op |
| PUT | /api/products/:id |
Actualizar un producto existente. Soporta cambio de foto. | Admin / Op |
| DELETE | /api/products/:id |
Desactivar un producto (soft-delete). No elimina datos. | Admin |
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| GET | /api/movements |
Listar movimientos con filtros: ?type=, ?product=, ?from=, ?to= |
Todos |
| POST | /api/movements |
Registrar un movimiento (entrada, salida o ajuste). Actualiza stock automáticamente. | Admin / Op |
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| GET | /api/categories |
Listar todas las categorías activas. | Todos |
| POST | /api/categories |
Crear una nueva categoría. | Admin / Op |
| PUT | /api/categories/:id |
Actualizar una categoría existente. | Admin / Op |
| DELETE | /api/categories/:id |
Desactivar una categoría. | Admin |
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| GET | /api/suppliers |
Listar todos los proveedores activos. | Todos |
| POST | /api/suppliers |
Crear un nuevo proveedor. | Admin / Op |
| PUT | /api/suppliers/:id |
Actualizar un proveedor existente. | Admin / Op |
| DELETE | /api/suppliers/:id |
Desactivar un proveedor. | Admin |
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| GET | /api/users |
Listar todos los usuarios del sistema. | Admin |
| POST | /api/users |
Crear un nuevo usuario. Body: {"username", "password", "fullName", "role"} |
Admin |
| PUT | /api/users/:id |
Actualizar un usuario (nombre, rol, contraseña). | Admin |
| DELETE | /api/users/:id |
Desactivar / reactivar un usuario. | Admin |
| Método | Endpoint | Descripción | Acceso |
|---|---|---|---|
| GET | /api/reports/summary |
KPIs del dashboard: total productos, valor del inventario, alertas de stock bajo, movimientos recientes. | Todos |
| GET | /api/reports/stock |
Reporte de niveles de stock actuales con filtros por categoría. | Todos |
| GET | /api/reports/movements |
Reporte de movimientos con filtros por fecha, tipo y producto. | Todos |
| GET | /api/reports/low-stock |
Productos cuyo stock actual está por debajo del mínimo definido. | Todos |
| GET | /api/reports/valuation |
Valorización del inventario: cantidad × precio por producto. | Todos |
# Paso 1: Obtener token de autenticación curl -X POST http://localhost:3001/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin123"}' # Respuesta: {"token":"eyJhbGciOiJIUzI1NiIs..."} # Paso 2: Usar el token para consultar productos curl http://localhost:3001/api/products \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." # Paso 3: Crear un nuevo producto curl -X POST http://localhost:3001/api/products \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \ -H "Content-Type: application/json" \ -d '{"name":"Cable UTP Cat6","sku":"CAB-006","categoryId":1,"stock":100,"minStock":20,"price":850}'
200 — Solicitud exitosa |
201 — Recurso creado |
400 — Datos inválidos |
401 — No autenticado |
403 — Sin permisos |
404 — No encontrado |
500 — Error del servidor
Manual del Administrador — v1.0
ACyEDE
Asociación Cooperadora y de Estímulo
de la Escuela
Julio 2026
📧 contacto@acyede.org.ar
🌐 www.acyede.org.ar