Tikvah POS — Documentación Interna

Versión: 4.x Producción: https://pos.siruf.cl Actualizado: Marzo 2026 Empresa: SIRUF

Visión general

Tikvah POS es un sistema de punto de venta (POS) SaaS chileno desarrollado por SIRUF, orientado a pequeñas y medianas empresas (PYMEs). Funciona como aplicación web progresiva (PWA) con soporte offline, pensada para funcionar en cualquier dispositivo — celular, tablet o computador — sin instalación.

🏪 Tipos de negocio

  • Almacén / tienda — módulo Caja
  • Restaurante — módulo Mesas y Comandas
  • Gimnasio — módulo Socios y Clases

👥 Roles de usuario

  • Dueño — acceso total
  • Admin — acceso total excepto super-admin
  • Cajero — solo caja y ventas

💰 Modelo de negocio

  • SaaS por suscripción mensual/anual
  • Planes: Básico, Profesional, Empresa
  • Pago via MercadoPago Chile

Stack tecnológico

CapaTecnologíaVersiónUso
FrontendReact + Vite18 / 7SPA, routing, estado
RoutingReact Routerv6Rutas del SPA
IconosLucide ReactTodos los íconos del sistema
BackendNode.js + ExpressESMAPI REST en server/
Base de datosSupabase (PostgreSQL)Todos los datos
AutenticaciónJWT custom via SupabaseLogin de usuarios
PWAService Worker customOffline + instalación
Caché offlineIndexedDB (idb.js)Ventas y productos offline
PagosMercadoPagoSuscripciones mensuales
Servidor webNginxProxy reverso + SSL
SSLLet's EncryptHTTPS automático
DNSNetlify DNSA record → 68.183.163.176

Arquitectura del sistema

┌─────────────────────────────────────────────────────────────┐ │ CLIENTE (Browser / PWA) │ │ │ │ React SPA ←→ Service Worker ←→ IndexedDB (offline) │ │ (Vite build en /dist) │ └────────────────────────┬────────────────────────────────────┘ │ HTTPS ┌────────────────────────▼────────────────────────────────────┐ │ NGINX (Proxy reverso) │ │ /api/* → 127.0.0.1:3001 /* → dist/index.html │ └────────────────────────┬────────────────────────────────────┘ │ ┌────────────────────────▼────────────────────────────────────┐ │ Node.js / Express (puerto 3001) │ │ │ │ server/ │ │ ├── index.js ← punto de entrada, middlewares │ │ ├── auth.js ← JWT, login, usuarios │ │ └── routes/ │ │ ├── caja.js ← sesiones de caja │ │ ├── productos.js ← CRUD productos + import Excel │ │ ├── inventario.js ← stock, movimientos │ │ ├── ventas.js ← ventas + anulación │ │ ├── gastos.js ← gastos del negocio │ │ ├── merma.js ← pérdidas de inventario │ │ ├── dashboard.js ← estadísticas y reportes │ │ ├── impuestos.js ← IVA, PPM, renta Chile │ │ ├── suscripciones.js ← planes + webhook MP │ │ ├── mesas.js ← restaurante: mesas │ │ ├── comandas.js ← restaurante: comandas │ │ ├── socios.js ← gimnasio: socios │ │ ├── clases.js ← gimnasio: clases │ │ └── siruf.js ← SIRUF Trueque: ofertas │ └────────────────────────┬────────────────────────────────────┘ │ @supabase/supabase-js ┌────────────────────────▼────────────────────────────────────┐ │ Supabase (PostgreSQL) │ │ + Row Level Security │ └─────────────────────────────────────────────────────────────┘

Flujo de autenticación

  1. Usuario envía POST /api/auth/login con email + password
  2. El servidor verifica en Supabase (pos_usuarios) con bcrypt
  3. Si válido, devuelve un JWT firmado (payload: id, negocio_id, rol)
  4. El cliente guarda el JWT en localStorage como pos_token
  5. Cada request del frontend incluye Authorization: Bearer <token>
  6. El middleware authMiddleware en Express verifica el token en cada ruta protegida

Deploy y producción

Servidor: DigitalOcean Droplet — Ubuntu 22.04 — IP: 68.183.163.176
Servicio: tikvah-pos (systemd) — reinicia automáticamente
URL: https://pos.siruf.cl

Pasos para deploy

# 1. Compilar el frontend (desde /home/siruf/tikvah-pos)
NODE_OPTIONS='--max-old-space-size=512' npx vite build

# 2. Reiniciar el servicio Node.js (sin sudo)
TPID=$(systemctl show tikvah-pos -p MainPID --value) && kill -TERM $TPID

# El servicio se reinicia solo con systemd y sirve el nuevo build

Variables de entorno (.env)

VariableUso
SUPABASE_URLURL del proyecto Supabase
SUPABASE_SERVICE_ROLE_KEYClave de servicio (admin)
JWT_SECRETFirma de tokens JWT
MP_ACCESS_TOKENMercadoPago para suscripciones
ADMIN_TOKENtikvah-admin-siruf-2026 — admin panel
PORT3001 (default)

Service Worker (PWA)

El archivo public/sw.js implementa cache-first para assets y network-first para la API. Cada deploy incrementa automáticamente CACHE_VERSION para invalidar el caché del navegador. Los usuarios ven un banner "Nueva versión disponible" cuando hay update.

Páginas y módulos del frontend

El frontend es un SPA con React Router. Todas las rutas están bajo el componente Layout que incluye el sidebar de navegación. Las rutas se definen en src/App.jsx.

RutaComponenteDescripciónRoles
/cajaCaja.jsxPunto de venta principalTodos
/mesasMesas.jsxRestaurante: mesas y comandasTodos
/gimnasioGimnasio.jsxGym: socios, clases, planesTodos
/productosProductos.jsxCatálogo de productosAdmin/Dueño
/inventarioInventario.jsxStock y movimientosTodos
/ventasVentas.jsxHistorial de ventasAdmin/Dueño
/dashboardDashboard.jsxEstadísticas y reportesAdmin/Dueño
/mermaMerma.jsxRegistro de pérdidasTodos
/gastosGastos.jsxGastos del negocioAdmin/Dueño
/impuestosImpuestos.jsxIVA, PPM y Renta ChileAdmin/Dueño
/saludSalud.jsxDiagnóstico financieroAdmin/Dueño
/suscripcionSuscripcion.jsxPlanes y pagosDueño
/metricasMetricas.jsxMétricas avanzadasAdmin/Dueño
/soporteSoporte.jsxChat con Kira AITodos
/configConfiguracion.jsxUsuarios, caja, aparienciaTodos

Módulo: Caja

Archivo: src/pages/Caja.jsx

Es el módulo más crítico del sistema. Permite registrar ventas en tiempo real con soporte completo offline.

Funciones principales

Modo offline

Cuando no hay conexión a internet, la caja sigue funcionando:

Requisito previo: Sesión de caja

Antes de vender, debe haber una sesión de caja abierta (POST /api/sesiones/abrir). Si no hay sesión, la caja muestra el modal para abrirla con el monto de apertura en efectivo. Las sesiones registran apertura y cierre con montos para el cuadre de caja.

Módulo: Productos

Archivo: src/pages/Productos.jsx

Funciones

Módulo: Inventario

Archivo: src/pages/Inventario.jsx

Funciones

Módulo: Ventas

Archivo: src/pages/Ventas.jsx

Funciones

Módulo: Gastos

Archivo: src/pages/Gastos.jsx

Funciones

Módulo: Merma

Archivo: src/pages/Merma.jsx

Registra las pérdidas de inventario que no son ventas: productos vencidos, dañados, robados o errores de ingreso.

Motivos de merma

Al registrar una merma, el stock del producto se descuenta automáticamente mediante un movimiento de inventario negativo.

Módulo: Dashboard

Archivo: src/pages/Dashboard.jsx

Panel de estadísticas y reportes del negocio. Consume múltiples endpoints del API.

Métricas incluidas

Módulo: Impuestos

Archivo: src/pages/Impuestos.jsx

Módulo específico para el sistema tributario chileno. Ayuda al dueño a preparar las declaraciones mensuales y anuales.

Funciones

Regímenes soportados

Módulo: Salud Financiera

Archivo: src/pages/Salud.jsx

Diagnóstico automático del estado financiero del negocio. Analiza la relación entre ingresos, gastos y margen bruto para detectar alertas temprana.

Módulo: Suscripción

Archivo: src/pages/Suscripcion.jsx

Planes disponibles

PlanPrecio mensualCaracterísticas
Básico$9.990Caja, productos, inventario, ventas básico
Profesional$24.990+ Dashboard, gastos, impuestos, merma
Empresa$64.990+ Restaurante/Gimnasio, métricas avanzadas, multi-caja

Flujo de pago

  1. Usuario selecciona plan y período (mensual/anual)
  2. Click en "Activar 7 días gratis" → POST /api/suscripciones/trial
  3. Redirige a MercadoPago para registrar tarjeta
  4. Al día 8 del trial, se cobra automáticamente
  5. Webhook de MP notifica el pago → activa o suspende la cuenta

Módulo: Configuración

Archivo: src/pages/Configuracion.jsx

Secciones

Módulo Restaurante (Mesas y Comandas)

Archivos: src/pages/Mesas.jsx | Backend: server/routes/mesas.js, comandas.js

Se activa cuando el negocio tiene tipo = 'restaurante' en la tabla pos_negocios. El ícono de Caja en el nav se reemplaza por Mesas con ícono de tenedor.

Funcionamiento

Módulo Gimnasio (Socios y Clases)

Archivo: src/pages/Gimnasio.jsx | Backend: server/routes/socios.js, clases.js

Se activa cuando el negocio tiene tipo = 'gimnasio'. El nav muestra "Socios" con ícono de mancuerna.

Pestañas

Módulo: Soporte / Kira AI

Archivo: src/pages/Soporte.jsx + src/components/KiraWidget.jsx

Kira es la asistente de IA de SIRUF. En el POS aparece de dos formas:

Conecta con el backend de Kira en https://api.siruf.cl/api/chat.

API REST — Resumen

Todas las rutas requieren Authorization: Bearer <jwt> excepto /api/auth/login.

Endpoints: Caja y Sesiones

POST
/api/sesiones/abrir
Abre una sesión de caja. Body: {caja, monto_apertura}
POST
/api/sesiones/:id/cerrar
Cierra la sesión. Body: {monto_cierre, notas}
GET
/api/sesiones/activa
Devuelve la sesión abierta del negocio actual
GET
/api/sesiones
Historial de sesiones. Params: limit

Endpoints: Productos e Inventario

GET
/api/productos
Lista de productos. Params: q, categoria_id, activo
POST
/api/productos
Crear producto
PUT
/api/productos/:id
Editar producto
DELETE
/api/productos/:id
Desactivar producto (soft delete)
GET
/api/productos/plantilla
Descarga template Excel para importación masiva
POST
/api/productos/importar
Importación masiva desde Excel/CSV. Body: {csv} o {xlsx_base64}
GET
/api/inventario
Stock actual de todos los productos con estado
POST
/api/inventario/ajuste
Ajustar stock. Body: {producto_id, cantidad, tipo, nota}. Tipos: entrada, ajuste
GET
/api/inventario/movimientos
Historial de movimientos de stock. Params: limit

Endpoints: Ventas

GET
/api/ventas
Historial de ventas. Params: desde, hasta, estado
GET
/api/ventas/:id
Detalle de una venta con sus ítems
POST
/api/ventas
Registrar venta. Body: {sesion_id, items, metodo_pago, descuento, nota}
PUT
/api/ventas/:id/anular
Anular venta y devolver stock. Body: {motivo}

Endpoints: Gastos y Merma

GET
/api/gastos
Lista de gastos. Params: desde, hasta, categoria
POST
/api/gastos
Registrar gasto. Body: {categoria, tipo, monto, descripcion, fecha}
PUT
/api/gastos/:id
Editar gasto
DELETE
/api/gastos/:id
Eliminar gasto
GET
/api/gastos/resumen
Totales por categoría
GET
/api/merma
Historial de merma
POST
/api/merma
Registrar merma. Motivos: vencimiento, daño, robo, error, otro

Endpoints: Dashboard y Reportes

GET
/api/dashboard/
Resumen principal: ventas del día, semana, mes
GET
/api/dashboard/ventas-por-dia
Serie temporal de ventas para el gráfico
GET
/api/dashboard/top-productos
Top 10 productos más vendidos
GET
/api/dashboard/ejecutivo
Resumen ejecutivo para panel de administrador
GET
/api/impuestos/config
Configuración tributaria del negocio

Endpoints: Admin y Pagos

GET
/api/admin/resumen
Panel super-admin. Header requerido: X-Admin-Token: tikvah-admin-siruf-2026
POST
/api/suscripciones/trial
Iniciar trial de 7 días. Body: {plan_codigo, periodo}
POST
/api/suscripciones/checkout
Generar link de pago MercadoPago
POST
/api/suscripciones/webhook
Webhook de MercadoPago (debe configurarse en dashboard de MP)

Base de datos — Tablas principales

TablaDescripciónColumnas clave
pos_negociosUn registro por negocio clienteid, nombre, tipo (almacen/restaurante/gimnasio), plan_codigo
pos_usuariosUsuarios del sistemaid, negocio_id, nombre, email, password_hash, rol, activo
pos_productosCatálogo de productosid, negocio_id, nombre, precio, costo, stock, stock_minimo, unidad, sku, barcode, activo, fecha_vencimiento
pos_categoriasCategorías de productoid, negocio_id, nombre
pos_sesionesSesiones de cajaid, negocio_id, usuario_id, caja, estado, monto_apertura, monto_cierre, opened_at, closed_at
pos_ventasCabecera de ventaid, negocio_id, sesion_id, usuario_id, total, descuento, metodo_pago, estado, nota
pos_venta_itemsÍtems de cada ventaid, venta_id, producto_id, nombre_producto, cantidad, precio_unitario, subtotal
pos_movimientos_stockHistorial de cambios de stockid, producto_id, tipo, cantidad, stock_antes, stock_despues, usuario_id, nota
pos_gastosGastos del negocioid, negocio_id, usuario_id, categoria, tipo (variable/permanente), monto, descripcion, fecha
pos_mermaPérdidas de inventarioid, negocio_id, producto_id, cantidad, motivo, descripcion, usuario_id
pos_suscripcionesSuscripciones SaaSid, negocio_id, plan_codigo, estado, periodo_inicio, periodo_fin, mp_subscription_id
pos_planesDefinición de planesid, codigo, nombre, precio_mensual, precio_anual, modulos (array)
pos_config_tributariaConfig fiscal del negocioid, negocio_id, regimen, rut_negocio, razon_social, tasa_ppm, tasa_renta, precios_con_iva
pos_credito_ivaFacturas de compra para crédito IVAid, negocio_id, proveedor, folio_factura, monto_neto, iva, fecha, concepto
pos_mesasMesas del restauranteid, negocio_id, numero, nombre, capacidad, activa
pos_comandasComandas abiertasid, mesa_id, usuario_id, estado, total, descuento, metodo_pago
pos_comanda_itemsÍtems de comandaid, comanda_id, producto_id, nombre_producto, cantidad, precio_unitario, subtotal
pos_sociosSocios del gimnasioid, negocio_id, nombre, email, telefono, fecha_nacimiento, notas
pos_membresiasMembresías de sociosid, socio_id, plan_id, fecha_inicio, fecha_fin, estado, metodo_pago
pos_membresia_planesPlanes de membresía del gymid, negocio_id, nombre, duracion_dias, precio
pos_clasesClases del gimnasioid, negocio_id, nombre, instructor, dia_semana, hora_inicio, hora_fin, cupo_max
pos_checkinsAsistencia al gimnasioid, socio_id, fecha, clase_id (opcional)

Roles y permisos

AcciónDueñoAdminCajero
Registrar ventas
Ver historial de ventas
Anular ventas
Crear/editar productos
Ajustar inventario
Ver Dashboard
Registrar gastos
Ver impuestos
Gestionar usuarios
Cerrar caja ajena
Ver suscripción/planes

Integración: MercadoPago

⚠️ Los webhooks de MP deben configurarse manualmente en mercadopago.cl → Desarrollo → Notificaciones IPN. URL: https://pos.siruf.cl/api/suscripciones/webhook

Flujo de suscripción

  1. Trial — el usuario registra su tarjeta en MP sin cargo inmediato (PreApproval). Al día 8 MP cobra automáticamente.
  2. Upgrade directo — genera una Preference de pago. MP redirige de vuelta con el resultado.
  3. Webhook authorized — activa la suscripción en la BD, actualiza periodo_fin.
  4. Webhook cancelled/paused — suspende el acceso. El usuario ve banner rojo.

Integración: SIRUF Trueque

URL: https://trueque.siruf.cl | Repo: sirufchile/siruf-trueque

SIRUF Trueque es una red de intercambio entre PYMEs. Permite mover inventario próximo a vencer o estancado sin pérdida monetaria. El POS se conecta en dos puntos:

La plataforma Trueque tiene un algoritmo de cadena que detecta intercambios multilaterales (A le da a B, B le da a C, C le da a A).

Integración: Kira AI

URL: https://api.siruf.cl | Repo: sirufchile/kira-agent

Kira es el asistente de IA de SIRUF, basado en Claude (Anthropic). En el POS aparece como:

El frontend envía mensajes a POST https://api.siruf.cl/api/chat con el slug = "tikvah-pos". Kira tiene acceso al contexto del sistema y puede responder preguntas sobre cómo usar cada módulo.

PWA y funcionamiento offline

Instalación

El sistema puede instalarse como app nativa en cualquier dispositivo. En móvil aparece un banner "Instalar Tikvah POS" que usa el evento beforeinstallprompt. Una vez instalado, funciona como app independiente sin barra del navegador.

Caché y versiones

Sincronización

Archivos clave del frontend

GitHub: Todos los repositorios están en la organización sirufchile en GitHub (privados). Repos: tikvah-pos, kira-agent, siruf-trueque.


Tikvah POS — Documentación interna SIRUF · Actualizado marzo 2026