Un sistema completo de punto de venta (POS) para restaurantes, diseñado para optimizar las operaciones diarias desde la toma de órdenes hasta la gestión administrativa. Esta aplicación web proporciona interfaces específicas para meseros, cocina, cajeros y administradores, con funcionalidades adaptadas a cada rol.
- Multi-rol: Interfaces específicas para meseros, cocina, cajeros y administradores
- Gestión de mesas: Asignación de mesas, estados y seguimiento de órdenes
- Menú digital: Categorías, platos, precios y descripciones
- Carrito de compras: Selección de productos, modificación de cantidades y comentarios
- Gestión de órdenes: Creación, seguimiento y finalización de órdenes
- Pagos: Procesamiento de pagos completos y parciales con diferentes métodos
- Caja registradora: Apertura, cierre, adiciones y retiros de efectivo
- Inventario: Control de ingredientes, recetas y alertas de stock bajo
- Reportes: Ventas, productos populares, transacciones y más
- Domicilios: Pedidos a domicilio con registro de clientes por teléfono, repartidores, tablero de estados y cobro anticipado o contra entrega (ver docs/delivery-module.md)
- Impresión: Tickets de cocina y facturas para clientes
- Promociones: Configuración y aplicación de descuentos y ofertas
- Configuración de negocio: Personalización de impuestos, propinas y datos del negocio
- Diseño responsive: Adaptado para dispositivos móviles y de escritorio
- Frontend: Next.js, React, TypeScript, Tailwind CSS
- Backend: Supabase (PostgreSQL)
- Estado: Zustand
- Gráficos: Shadcn
- Autenticación: Supabase Auth
- Almacenamiento: Supabase Storage
- Tiempo real: Supabase Realtime
- Node.js (v18 o superior)
- npm o yarn
- Cuenta en Supabase
git clone https://github.com/tu-usuario/restaurant-pos.git
cd restaurant-posnpm install
# o
yarn installCrea un archivo .env en la raíz del proyecto con las siguientes variables:
NEXT_PUBLIC_SUPABASE_URL=tu_url_de_supabase
NEXT_PUBLIC_SUPABASE_ANON_KEY=tu_clave_anonima_de_supabase
SUPABASE_SERVICE_ROLE_KEY=tu_clave_de_servicio_de_supabase
La base de datos local se levanta con la Supabase CLI.
Todo el esquema vive en un único directorio versionado, supabase/migrations/:
pnpm supabase start # levanta db, auth, storage, realtime y studio
pnpm supabase db reset # aplica las migraciones y carga supabase/seed.sqlpnpm supabase status muestra la URL local y las claves (API_URL,
ANON_KEY, SERVICE_ROLE_KEY) para pegarlas en el .env de la sección anterior.
Para borrar la base local y reconstruirla desde cero (migraciones + datos de ejemplo):
pnpm supabase db resetWarning: supabase db reset destruye los datos locales (perfiles, mesas, comandas).
Para detener los contenedores: pnpm supabase stop (agrega --no-backup para borrar también los datos locales).
npm run dev
# o
yarn devLa landing page pública estará disponible en http://localhost:3000 y el portal del sistema (login y vistas por rol) en http://localhost:3000/portal.
El sistema se usa desde /portal: tras iniciar sesión, se mostrará una pantalla de selección de perfil:
- Mesero: Para tomar órdenes y gestionar mesas
- Cocina: Para ver y procesar órdenes
- Cajero: Para gestionar pagos y la caja registradora
- Operador de domicilios: Para tomar pedidos a domicilio, despacharlos y cerrarlos
- Administrador: Para configuración y reportes
Cada perfil está protegido por una contraseña que puede configurarse en el panel de administración.
supabase/seed.sql (cargado por pnpm supabase db reset) crea estas cuentas. Son solo para desarrollo local; no las uses en producción.
| Correo | Contraseña | Rol |
|---|---|---|
admin@restaurant.com |
admin123 |
Administrador |
carlos@restaurant.com |
carlos123 |
Cajero |
maria@restaurant.com |
maria123 |
Mesero |
deiby@restaurant.com |
deiby123 |
Mesero |
tester@restaurant.com |
tester123 |
Mesero |
domicilios@restaurant.com |
domicilios123 |
Operador de domicilios |
- Selecciona una mesa disponible
- Asigna un mesero (si es necesario)
- Selecciona productos por categoría
- Agrega productos al carrito
- Ajusta cantidades y agrega comentarios si es necesario
- Envía la orden a cocina
En dispositivos móviles, el carrito se muestra como un botón flotante que abre un modal al hacer clic.
- Visualiza las órdenes pendientes
- Marca los productos como "en preparación" y luego como "listos"
- Imprime tickets de cocina si es necesario
- Abre la caja registradora al inicio del turno
- Selecciona mesas con órdenes activas
- Procesa pagos (completos o parciales)
- Selecciona método de pago
- Imprime facturas
- Registra entradas y salidas de efectivo
- Cierra la caja al final del turno
El operador de domicilios trabaja desde un tablero de pedidos agrupados por estado.
Nuevo domicilio (botón "Nuevo domicilio"):
- Busca al cliente por teléfono; si existe, se muestran sus direcciones guardadas (también puede registrar un cliente o una dirección nueva y guardarla)
- Selecciona los productos del menú (el servidor toma los precios del menú)
- Revisa el valor del domicilio: se sugiere el configurado por el administrador y es editable por pedido (no lleva impuesto ni propina)
- Elige el modo de pago: prepago (Nequi/transferencia) o contra entrega; para contra entrega puede indicar "cambio para"
- Agrega notas (máximo 300 caracteres) y crea el pedido; se envía la comanda a cocina
Estados: recibido → preparando → listo → en camino → entregado, o fallido (con motivo). Un pedido fallido puede reenviarse o cancelarse. Las transiciones se validan en el servidor. No se puede cancelar un pedido que ya tiene un pago.
Despacho: al enviar el pedido se elige un repartidor activo; en un reenvío se puede elegir otro. El tablero muestra si el pedido está pagado o pendiente.
Cobro: el pago se registra con "Registrar pago" en el tablero o desde el panel Domicilios por cobrar de la vista de Cajero. Ambos requieren una caja abierta (el operador no abre ni cierra cajas) y suman el valor del domicilio al total.
Cocina: los pedidos a domicilio comparten la cola con la etiqueta DOMICILIO y muestran al cliente en lugar de la mesa. Al servir el último producto, el pedido pasa automáticamente a "listo".
- Gestiona el menú (categorías y platos)
- Configura mesas
- Administra personal
- Controla inventario
- Configura promociones
- Visualiza reportes y estadísticas
- Configura parámetros del negocio (impuestos, propinas, etc.)
En Configuración también hay dos pestañas relacionadas con domicilios:
- Repartidores: crea, edita y activa/desactiva repartidores (nombre y teléfono; no inician sesión) y define el valor sugerido del domicilio
- Personal: crea cuentas de acceso (correo, contraseña y rol: mesero, cocina, cajero u operador de domicilios) mediante la Edge Function
create-staff-account. Solo la puede invocar un administrador, el restaurante se toma del administrador que la invoca y no permite crear cuentas de rol administrador. Ver docs/delivery-module.md y DOCKER.md para servirla o desplegarla
restaurant-pos/
├── app/ # Rutas y páginas de Next.js
├── components/ # Componentes React
│ ├── admin/ # Componentes para administración
│ ├── auth/ # Componentes de autenticación
│ ├── cashier/ # Componentes para cajeros
│ ├── kitchen/ # Componentes para cocina
│ ├── layout/ # Componentes de estructura
│ ├── pos/ # Componentes del punto de venta
│ ├── printing/ # Componentes de impresión
│ ├── profiles/ # Selección de perfiles
│ ├── theme/ # Componentes de tema
│ ├── ui/ # Componentes de UI reutilizables
│ └── views/ # Vistas principales por rol
├── hooks/ # Hooks personalizados
├── lib/ # Utilidades y servicios
│ └── supabase/ # Servicios de Supabase
├── public/ # Archivos estáticos
├── store/ # Estado global (Zustand)
├── types/ # Definiciones de tipos TypeScript
└── utils/ # Funciones utilitarias
- Autenticación: Gestión de perfiles y acceso mediante contraseñas
- Estado Global: Almacenamiento de configuración, estado de caja, y datos del POS
- Servicios de Supabase: Comunicación con la base de datos para CRUD y operaciones complejas
- Tiempo Real: Actualización en tiempo real de órdenes, mesas y estados
- categories: Categorías de productos
- dishes: Platos y bebidas
- ingredients: Ingredientes para el inventario
- tables: Mesas del restaurante
- profiles: Usuarios del sistema
- orders: Órdenes de clientes
- order_items: Productos en cada orden
- cash_registers: Registros de caja
- payment_transactions: Transacciones de pago
- cash_transactions: Movimientos de efectivo
- promotions: Promociones y descuentos
- business_config: Configuración del negocio
En el panel de administración, puedes configurar:
- Porcentaje de impuestos
- Porcentaje de propina sugerida
- Porcentaje de sugerencia de precio
Activa o desactiva el control de inventario para:
- Seguimiento automático de ingredientes
- Alertas de stock bajo
- Prevención de venta de productos sin stock
Configura contraseñas personalizadas para cada rol:
- Mesero
- Cocina
default: 1234 - Cajero
default: 5678 - Administrador
default: 9999
Personaliza la información que aparece en las facturas:
- Nombre del negocio
- Dirección
- Teléfono
- NIT/RUT/RFC
npm run test
# o
yarn testLa lógica pura de TypeScript (lib/payments, store) se prueba con Vitest en
entorno Node, sin navegador:
pnpm test # una pasada
pnpm test:watch # modo interactivoPruebas de la capa de impresión en Python (desde la raíz del repositorio):
python3 -m unittest pos/test_print_renderer.pyOtras verificaciones: pnpm typecheck y pnpm build.
El comportamiento de la base de datos (políticas RLS, permisos, RPCs) se cubre con
pruebas SQL de pgTAP en supabase/tests/, que se ejecutan con la Supabase CLI
contra la base local (requiere pnpm supabase start):
pnpm test:db # todos los archivos
pnpm supabase test db supabase/tests/001_bootstrap.test.sql # uno soloCada archivo es autónomo (BEGIN; ... SELECT plan(n); ... finish(); ROLLBACK;), así
que la base nunca se modifica. Consulta supabase/tests/README.md para escribir
pruebas y suplantar los roles anon / authenticated.
Complementario a la aplicación web, este sistema se encarga de:
- Escuchar en tiempo real los eventos de Supabase (comandas y facturas).
- Imprimir automáticamente en impresoras térmicas USB o de red.
- Ejecutarse al iniciar Windows gracias al instalador.
Los payloads de comanda y factura incluyen un bloque opcional delivery (aditivo). Con él, la comanda se imprime como COMANDA — DOMICILIO con el cliente y las notas, y la factura muestra CLIENTE / TEL / DIRECCION en lugar de MESA / MESERO, la línea DOMICILIO dentro del total y CAMBIO PARA en pedidos contra entrega. Los payloads sin delivery se imprimen igual que antes. Un listener antiguo ignora ese bloque: la comanda de un domicilio sale como COMANDA — Mesa None y la factura no trae la línea DOMICILIO, de modo que su TOTAL SIN PROPINA no incluye la tarifa aunque TOTAL A PAGAR sí. Actualiza el ejecutable de impresión antes de usar domicilios.
- Conexión en tiempo real a Supabase (canales de comandas y facturas).
- Soporte para impresoras USB y de red.
- Manejo de credenciales en entorno seguro (cifrado en AppData).
- Autoarranque al iniciar Windows.
- Compatible con Windows 10/11.
- Windows 10 o superior.
- Python 3.11 o superior (solo para desarrollo).
- Impresoras compatibles con ESC/POS o de red.
Estas son las librerías necesarias para desarrollo y empaquetado del sistema de impresión en Python.
Instala todas desde requirements.txt o individualmente:
pip install python-dotenv customtkinter pystray Pillow html2text escpos-python pywin32 usbO crea un requirements.txt con:
python-dotenv
customtkinter
pystray
Pillow
html2text
escpos-python
pywin32
usb
| Librería | Uso Principal |
|---|---|
| python-dotenv | Cargar variables desde .env en desarrollo |
| customtkinter | Interfaces gráficas para capturar credenciales |
| pystray | Ícono en la bandeja del sistema Windows |
| Pillow | Manejo de imágenes para impresión |
| html2text | Convertir HTML a texto plano para impresoras |
| escpos-python | Control de impresoras USB y de red ESC/POS |
| pywin32 | Cifrado/descifrado con DPAPI (win32crypt) |
| usb | Detección de dispositivos USB |
Incluye este bloque debajo de la sección Requisitos Previos o Configuración Inicial para que esté completamente documentado. ¿Te gustaría que también lo traduzca al inglés si vas a publicarlo internacionalmente?
pos-listener/
├── app.py # Punto de entrada
├── requirements.txt # Dependencias
├── vipe_pos_installer.iss # Script de instalador Inno Setup
└── assets/
└── vipe-pos.ico # Icono del sistema
pip install -r requirements.txtCrea un archivo .env:
SUPABASE_URL=https://tu-proyecto.supabase.co
SUPABASE_KEY=tu-api-key
ENVIRONMENT=dev
python app.py --devpip install pyinstaller pywin32pyinstaller --noconfirm --onedir --windowed --icon=assets/vipe-pos.ico --hidden-import=win32crypt --hidden-import=pywintypes app.pyEl ejecutable se creará en dist/vipe_pos/vipe_pos.exe.
Descarga desde https://jrsoftware.org/isinfo.php
Esto generará un archivo VipePOS_Setup.exe.
- Ejecuta
VipePOS_Setup.exe. - El sistema se instalará en
C:\Program Files\Vipe POS. - Se creará un acceso directo en el menú Inicio, Escritorio y carpeta de inicio (autoarranque).
- La primera vez que se ejecute, solicitará las credenciales de Supabase.
- Las credenciales se almacenarán cifradas en
%APPDATA%\VipePOS\credentials.dat.
- Verifica que el sistema esté corriendo en segundo plano (ícono en la bandeja del sistema).
- Realiza una orden desde la app web.
- La impresora debería recibir automáticamente la comanda o factura.
Si necesitas cambiar las credenciales:
- Elimina el archivo
%APPDATA%\VipePOS\credentials.dat. - Vuelve a ejecutar el sistema y se te pedirá ingresarlas nuevamente.
¿Quieres que prepare también un ejemplo de .gitignore para este proyecto Python?
La aplicación se despliega en Railway con el Dockerfile del repositorio (configurado en railway.json). Supabase sigue siendo la base de datos.
| Ambiente | Rama | Despliegue |
|---|---|---|
production |
main |
Automático en cada push a main |
staging |
dev |
Automático en cada push a dev |
Cada ambiente necesita estas variables en el servicio web de Railway. Se usan en el build, así que un cambio requiere redesplegar:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
Para construir localmente:
pnpm build- Haz un fork del repositorio
- Crea una rama para tu característica (
git checkout -b feature/amazing-feature) - Haz commit de tus cambios (
git commit -m 'Add some amazing feature') - Haz push a la rama (
git push origin feature/amazing-feature) - Abre un Pull Request
Este proyecto está licenciado bajo la Licencia MIT - ver el archivo LICENSE para más detalles.
Para soporte, contacta a rade@support.com o abre un issue en el repositorio.
Desarrollado con ❤️ para restaurantes que buscan optimizar sus operaciones.
