06 — TPV (Terminal Punto de Venta)

Módulo más completo del sistema ZEUMAX.
Este documento describe en detalle la operación diaria del TPV, la herramienta que el cajero utiliza para atender a los clientes en el local físico del restaurante.


Introducción

El TPV (Terminal Punto de Venta) es el corazón operativo de tu restaurante. Es la herramienta que el cajero utiliza directamente para atender a los clientes que están en el local, gestionar mesas, enviar pedidos a cocina, cobrar, dividir cuentas, controlar stock y mucho más.

En el sistema ZEUMAX, el TPV es una aplicación móvil/tablet desarrollada en React Native + Expo, diseñada para funcionar en dispositivos Android e iOS. Reemplaza o complementa al TPV tradicional de hardware, ofreciendo una experiencia táctil, intuitiva y conectada con todo el ecosistema de la plataforma: el panel de administración, el modulo de delivery, el control de almacén y las impresoras térmicas.

El cajero interactúa con el TPV a través de una interfaz optimizada para pantallas táctiles, utilizando NativeWind (Tailwind para React Native) para una estética limpia, rápida y consistente. La paleta visual se basa en el verde corporativo #8BC34A para acciones primarias (botones de cobro, enviar a cocina, confirmar, precios de productos) y la barra superior oscura #424242 para encabezados y navegación. En modo oscuro el acento cambia a azul #3B82F6.

El estado de la aplicación se gestiona con Zustand y la persistencia local con MMKV, lo que garantiza que el TPV funcione de forma fluida incluso en momentos de alta carga de trabajo.


Requisitos Técnicos y Operativos

Para operar el TPV de ZEUMAX, se requiere:

Requisito Detalle
Dispositivo Tablet o móvil Android/iOS con pantalla táctil. Recomendado tablet de 10" para mejor visibilidad del plano de mesas.
Conexión a internet Obligatoria para sincronización con el backend, envío de pedidos a cocina, impresión en red y actualizaciones en tiempo real.
Sistema operativo Android 8.0+ o iOS 14+. La app se distribuye vía Expo o tiendas de aplicaciones.
Impresora térmica Recomendada Bluetooth o Red (WiFi/Ethernet) para impresión de tickets de cocina, barra y caja.
Cajón de dinero Opcional. Modelo inteligente compatible (CashDro) que se abre automáticamente al cobrar.
Pantalla cliente Opcional. Visualizador de precios para que el cliente vea el total mientras se cobra.
Credenciales TPV El usuario debe tener un PIN de TPV otorgado desde el Panel de Administración. El guard de acceso es auth:tpv_api.
Feature flags El middleware CheckTpvFeature verifica que el establecimiento tenga activado el módulo TPV en su plan.

Login y Apertura de Caja

1.1 Pantalla de Login TPV

Al abrir la aplicación TPV, el cajero se encuentra con la pantalla de inicio de sesión.


     ZEUMAX TPV                   


        PIN de usuario           

        1   2   3                
        ⌫            
        4   5   6                

        7   8   9                

              0                   



     Guard: auth:tpv_api          

  • Teclado numérico grande: diseñado para uso rápido en tablet. Los botones son de tamaño táctil generoso para evitar errores.
  • Borrar (⌫): elimina el último dígito introducido.
  • Confirmar ( ): valida el PIN.
  • Mensaje de error: si el PIN es incorrecto, aparece un toast en rojo: "PIN incorrecto. Inténtalo de nuevo."
  • Timeout de sesión: si el TPV permanece inactivo un tiempo configurable, se bloquea automáticamente y pide el PIN de nuevo.

Nota: El PIN es de 4 a 6 dígitos numéricos, configurado por el administrador desde el Panel Admin. Cada usuario TPV tiene su propio PIN.

1.2 Apertura de Caja (Sesión TPV)

Una vez autenticado, el sistema verifica si hay una sesión de caja abierta. Si no la hay, obliga a realizar la apertura de caja antes de poder operar.


     Apertura de Caja              

     Fecha: 20/06/2026            
     Usuario: Carlos M.           
     Local: Restaurante ZEUMAX   

     Fondo de caja inicial:       

      € 0,00                     
      [Teclado numérico]          


     Instrucciones:                
   Cuenta el efectivo que tienes   
   en la caja al inicio del turno. 


        CONFIRMAR APERTURA       


     Cancelar y salir             

Flujo de apertura:
1. Fecha y usuario: se muestra automáticamente.
2. Conteo físico: el cajero cuenta el efectivo real que hay en la caja (monedas y billetes).
3. Introducir monto: teclea la cantidad en el campo numérico. El teclado permite decimales para monedas de céntimo.
4. Confirmar: botón verde grande #8BC34A. Al tocarlo, se registra la sesión en el backend (TpvSessionController).
5. Vista principal: se desbloquea el acceso completo al TPV.

Importante: No se puede crear ningún pedido ni realizar ninguna operación de venta hasta que la caja esté abierta. El sistema muestra un modal bloqueante si se intenta.


Vista Principal del TPV

Tras la apertura, el cajero accede a la pantalla principal, que muestra una TopMenuBar oscura con menús desplegables (Consulta, Caja, Almacén, Administración) y accesos directos. El punto de venta presenta un sidebar vertical de categorías a la izquierda, el grid de productos en el centro y el carrito fijo a la derecha.


   ZEUMAX TPV                    ← TopMenuBar oscura #424242


   [    Principal  ] [   Mesas ] 
   [    Informes  ] [   Más  ] 


        NUEVO PEDIDO               ← Botón principal verde



        Pedidos activos (3)      
        Hold orders (1)          
        Alertas (2)              



        Resumen rápido hoy:      
      Ventas: € 1.245,00          
      Tickets: 42                 
      Ticket medio: € 29,64       



                              ← Tabs inferiores

Módulos disponibles desde la vista principal:
- ** Principal: acceso rápido a nuevo pedido, pedidos activos, hold orders, alertas y resumen del día.
- ** Mesas
: plano visual del restaurante con zonas y mesas.
- ** Informes: ventas por período, productos, categorías, empleados, etc.
- ** Más
: configuración, stock, clientes, impresoras, turnos, festivos, perfil TPV.


Flujo de Venta Principal (Paso a Paso)

Este es el flujo más importante del TPV. Describe la operación completa desde que llega un cliente hasta que se libera la mesa.

Paso 1: Seleccionar Mesa o Pedido Para Llevar

El cajero inicia un nuevo pedido desde el botón principal "NUEVO PEDIDO" o desde la pestaña Mesas.


     Nuevo Pedido                  


       Salón     Terraza          
     Principal                    

       Barra     Privado          
                  1               


   Zona: Salón Principal           



     1    2    3    4            


     5    6    7    8            


     9    10   11   12           


     Libre    Ocupada    Reservada
     Cuenta pedida                


        PARA LLEVAR (Takeaway)     



        Nueva mesa rápida        


Vista de plano de mesas:
- Zonas: tabs horizontales para cambiar entre zonas del restaurante (Terraza, Salón Principal, Barra, Privado 1...). Cada zona se configura desde el Panel Admin (TableAreaController).
- Grid de mesas: cada mesa es un cuadrado/card con:
- Número de mesa (ej: 1, 2, 3...)
- Capacidad (icono pequeño de personas: )
- Color de estado:
- Verde: Libre / Disponible
- Rojo: Ocupada (tiene un pedido activo)
- Amarillo: Reservada (reserva confirmada para más tarde)
- Naranja: Cuenta pedida (el cliente pidió la cuenta, pendiente de cobro)
- Para llevar: botón grande gris/azul claro para pedidos que no ocuparán mesa (takeaway/delivery desde el local).
- Nueva mesa rápida: si el plano no está actualizado, permite crear una mesa temporal.

Acción: El cajero toca una mesa verde (libre) o el botón "Para llevar". Si toca una mesa ocupada, abre el pedido activo de esa mesa para editarlo o cobrarlo.

Interacción táctil: Las mesas son botones táctiles grandes. Al tocar una mesa libre, cambia visualmente a un estado "seleccionada" (borde verde #8BC34A) y aparece el botón "Abrir pedido" en el panel lateral.

Paso 2: Tomar el Pedido (Pantalla de Menú)

Tras seleccionar la mesa, se abre la pantalla de toma de pedido.


   ←   Pedido Mesa 3 (Terraza)    
     4 comensales                  



    Burg.  Pizza  Pasta        ← Categorías (scroll horiz.)
      Act.                        

    Ensal. Bebidas Postre     


   Categoría: Hamburguesas         



     Clásica    Doble     Bacon 
     €12,00     €16,00    €14,5 
     [img]      [img]   [img] 




     Cheese     Spicy              
     €13,00     €13,50             



     COMANDA (2 items)            

     1x Hamburguesa Clásica       
        €12,00                   
     2x Coca-Cola                 
        €6,00                    

     SUBTOTAL: €18,00            


       COBRAR    ENVIAR A       
                   COCINA         


Estructura de la pantalla de menú:

Barra superior (TopMenuBar oscura #424242):
- Flecha para volver al plano de mesas.
- "Pedido Mesa X" con nombre de zona.
- ** X comensales**: indicador de capacidad de la mesa.

Sidebar de categorías (vertical, ~118 px):
- Tabs deslizables con iconos y nombre: Hamburguesas, Pizzas, Pastas, Ensaladas, Bebidas, Postres...
- La categoría activa tiene fondo verde #8BC34A con texto blanco. Las demás muestran fondo transparente con texto negro.
- Si hay muchas categorías, se desplaza verticalmente con el dedo.

Grid de productos (7 columnas en tablet):
- Cada producto es una card táctil cuadrada con relación de aspecto ~0.92:
- Imagen del producto (si está disponible; si no, icono genérico de plato).
- Badge de precio verde #8BC34A en la esquina superior derecha.
- Nombre del producto (dos líneas máximo).
- Badge de oferta si tiene descuento activo.
- Badge de stock bajo si el producto tiene stock limitado y está por agotarse.
- Badge de no disponible en gris si el producto está marcado como agotado.

Nota: Los precios y la moneda vienen del backend (ProductTariffController). No hay valores hardcoded en la app.

Paso 2.1: Modal de Producto (Bottom Sheet)

Al tocar un producto, aparece un bottom sheet (panel que sube desde abajo) con las opciones del producto.





           HAMBURGUESA           
          CLÁSICA                 

         [imagen grande]          

         €12,00                   


        FORMATO:                 
        Tapa (€8,00)                ← Radio buttons
        Media (€10,00)            
        Ración (€12,00)           
        Para llevar (€11,00)      

        EXTRAS:                   
        Doble queso (+€2,00)       ← Checkboxes
        Extra bacon (+€1,50)      
        Sin cebolla (€0,00)      
        Guacamole (+€1,00)        

        NOTA:                    

        Sin salsa BBQ                ← TextInput


        CANTIDAD:                

        -   2   +                  ← +/-


        TOTAL: €14,00            
      (2 x €12,00 + extras)       


           AÑADIR                




Elementos del bottom sheet:
- Imagen grande: foto del producto en calidad media.
- Formato de producto (ProductFormatController): radio buttons para elegir presentación. Ejemplo: Tapa, Media, Ración, Para llevar. Cada formato tiene su precio. Solo se puede seleccionar uno.
- Extras/Modificadores (TpvModifierGroupController): checkboxes para añadir/quitar ingredientes. Ejemplo: "Doble queso (+€2,00)", "Sin cebolla (€0,00)", "Extra bacon (+€1,50)". Cada modificador puede tener precio adicional o ser gratuito.
- Nota: campo de texto libre para indicaciones especiales ("Sin salsa BBQ", "Poco hecho", "Para alérgico a frutos secos"). El texto se muestra en la comanda y en el ticket de cocina.
- Cantidad: controles + y - para añadir múltiples unidades del mismo producto con las mismas opciones. La cantidad mínima es 1.
- Total dinámico: se actualiza automáticamente al cambiar formato, extras o cantidad.
- Botón AÑADIR: verde #8BC34A, grande, táctil. Al pulsar, el producto se añade a la comanda lateral y el bottom sheet se cierra con animación de deslizamiento hacia abajo.

Menú del día (DailyMenuController): si el producto es un "Menú del día", el bottom sheet muestra pasos secuenciales: "Elige primer plato" → "Elige segundo plato" → "Elige postre" → "Elige bebida", cada uno con sus opciones configurables y precio fijo del menú.

Paso 3: Comanda (Lista de Productos Añadidos)

En la parte derecha (en tablet) o inferior (en móvil) se muestra la comanda en tiempo real.

  COMANDA — Mesa 3


  1x   Hamburguesa Clásica       
     Media | Doble queso          
     Sin cebolla                  
     €12,00                    

  2x   Patatas fritas            
     €8,00                     

  1x   Coca-Cola                 
     €2,50                     

  1x   Ensalada César            
     Ración | Sin crutons         
     €9,50                     



  SUBTOTAL:        €32,00         
  DESCUENTO:      -€3,20 (10%)    
  IMPUESTOS (10%): €3,20          

  TOTAL:           €32,00         

  [  Aplicar cupón]              
  [  Aplicar cliente]            

Cada línea de producto muestra:
- Cantidad (ej: 1x, 2x).
- Icono y nombre del producto.
- Variantes/formato seleccionado (ej: "Media", "Ración").
- Modificadores (ej: "Doble queso", "Sin cebolla").
- Nota en letra más pequeña e itálica ("Poco hecho").
- Precio total de esa línea (cantidad × precio unitario + extras).
- ** Eliminar: tocar el icono de papelera quita el producto de la comanda. Pide confirmación si ya se envió a cocina.
- ** Editar
: tocar el icono de lápiz reabre el bottom sheet para modificar cantidad, extras o nota.

Totales:
- Subtotal: suma de todos los productos antes de impuestos y descuentos.
- Descuento: si se aplica un cupón o oferta (TpvOfferController), aparece la línea de descuento con monto y porcentaje.
- Impuestos: desglose por tipo de impuesto. Los impuestos se configuran en el backend (TpvInvoiceController), no están hardcodeados en la app. Pueden ser [0%, 8%, 16%, 18%] o los que el administrador configure.
- Total: monto final a pagar.

Acciones adicionales en la comanda:
- ** Aplicar cupón: abre un campo para escanear o teclear código de cupón. Valida contra el backend y aplica el descuento si es válido.
- ** Aplicar cliente
: abre buscador de clientes para asociar el pedido a un cliente (fidelidad, factura con datos, etc.).

Paso 4: Enviar a Cocina ‍

Cuando el pedido está listo para que cocina lo prepare, el cajero pulsa el botón grande verde "ENVIAR A COCINA".



     Confirmar envío a cocina?    

   Se imprimirá ticket en:         
     Impresora Cocina (Red)      
     Impresora Barra (BT)        

   Productos a enviar:             
   • 1x Hamburguesa Clásica        
   • 2x Patatas fritas             
   • 1x Ensalada César             


      CANCELAR     CONFIRMAR     



Al confirmar:
1. Se envía la orden al backend (TpvOrderController).
2. El backend genera un ticket de cocina con formato optimizado para impresoras térmicas:
- Número de mesa y zona en grande.
- Hora del pedido.
- Lista de productos con cantidad, nombre, formato, modificadores y notas en letra grande.
- Separación por categorías de impresora (cocina, barra, postre).
3. Se envía a la impresora térmica configurada (Bluetooth o Red).
4. Los productos en la comanda cambian de estado visualmente: aparece un badge verde "Enviado" junto a cada línea.
5. Si hay impresora asignada por categoría (ej: bebidas a Barra, comidas a Cocina), se envían tickets separados.

Si no hay impresora configurada: aparece un modal de error rojo: "No hay impresora configurada para esta categoría. Configúrala en Ajustes > Impresoras."

Paso 5: Cocina Lista (Kitchen Call)

Cuando el equipo de cocina termina de preparar un plato, puede marcarlo como listo desde su propia interfaz (o manualmente el cajero lo marca desde el TPV).


     Kitchen Call — 14:32        


        Hamburguesa Clásica       
      Mesa 3 — Terraza              
        LISTO                      

      [Marcar servido]              



        Ensalada César            
      Mesa 3 — Terraza              
      ⏳ PENDIENTE                  


     Llamar a cocina (URGENTE)    


Kitchen Call:
- Pantalla dedicada accesible desde el botón de campana en la barra superior.
- Muestra lista de productos pendientes y listos por mesa.
- Marcar servido: al tocar, el producto desaparece de la lista de pendientes y aparece en el historial de la comanda como "Servido".
- Llamada urgente: botón para enviar notificación a cocina si un plato se retrasa.
- Sonido: el dispositivo puede emitir un sonido de campana cuando llega un nuevo "listo" (configurable en ajustes).

Paso 6: Checkout (Cobro)

El cliente termina de comer y pide la cuenta. El cajero toca el botón "COBRAR".


   ←   Checkout — Mesa 3         

     RESUMEN DEL PEDIDO           

     1x Hamburguesa Clásica      
        €12,00                   
     2x Patatas fritas            
        €8,00                    
     1x Coca-Cola                 
        €2,50                    
     1x Ensalada César            
        €9,50                    

     SUBTOTAL:    €32,00         
     DESCUENTO:   -€0,00         
     IMPUESTOS:    €3,20         

     TOTAL:       €32,00         


     Cliente: [Buscar por tel...] 
     Cupón: [-----]              

     MÉTODO DE PAGO:              


    Efectivo  Tarjeta  Wallet     
     [Act.]                       


     EFECTIVO:                    
   Entregado: €40,00               
   Cambio:     €8,00               


        CONFIRMAR PAGO €32,00     


   [  Pago mixto]                 
   [  Enviar factura por email]   
   [  Factura con datos fiscales]   


Pantalla de checkout:

Resumen del pedido:
- Lista completa de productos con precios (no editable, solo informativo).
- Subtotal, descuento, impuestos y TOTAL en grande y negrita.

Cliente:
- Campo de búsqueda por teléfono. Al teclear 3+ dígitos, aparece lista de clientes coincidentes (TpvCustomerController).
- Al seleccionar un cliente, se muestra su nombre, teléfono y puntos de fidelidad disponibles.
- Opción de "Cliente ocasional" para ventas sin registrar cliente.

Cupón:
- Campo para código de cupón. Al validar, muestra el descuento aplicado y el nuevo total.

Método de pago:
- ** Efectivo: activo por defecto. Muestra teclado numérico para indicar "Entregado". Calcula automáticamente el cambio (Entregado - Total). Si el cambio es negativo, el botón de confirmar se desactiva.
- ** Tarjeta
: botón para marcar pago con tarjeta. No requiere entregado/cambio (el TPV no procesa la pasarela de pago, solo registra el método). Se integra con datáfono externo si está disponible.
- ** Wallet / App: pago con el saldo interno del cliente (fidelidad) o monedero digital.
- ** Pago mixto
: permite dividir el total entre varios métodos. Ej: €20 en efectivo + €12 con tarjeta. Al activar, aparecen campos para asignar montos a cada método. La suma debe coincidir exactamente con el total.

Confirmar pago:
- Botón verde grande #8BC34A con el monto total.
- Al tocar, se envía el pago al backend (TpvOrderController).
- Si hay éxito, se muestra un toast verde: "Pago registrado correctamente. "
- Si hay error (stock insuficiente, sesión de caja cerrada, impresora desconectada), aparece modal de error con detalle.

Paso 7: Ticket y Cierre Automático

Tras confirmar el pago:

  1. Se imprime ticket de caja automáticamente en la impresora de caja configurada.
  2. Layout del ticket (TpvInvoiceController):

    • Logo del restaurante (si está configurado).
    • Nombre, dirección, NIF/CIF del restaurante.
    • Número de ticket y serie.
    • Fecha y hora.
    • Lista de productos, cantidades, precios.
    • Subtotal, descuento, impuestos, total.
    • Método de pago y cambio (si fue efectivo).
    • Mensaje de agradecimiento personalizado.
    • Código QR (opcional, para factura digital).
  3. Cajón de dinero: si hay un CashDro o cajón inteligente configurado (TpvPeripheralController), se envía la señal de apertura automática al cobrar en efectivo.

  4. Pantalla cliente: si hay pantalla visualizadora conectada, muestra el total, el entregado y el cambio para que el cliente lo vea.

  5. Opciones post-cobro:

  6. ** Enviar factura por email**: campo para email del cliente. El backend (TpvEmailController) envía la factura en PDF.
  7. ** Factura completa**: si el cliente necesita factura con datos fiscales (NIF, nombre empresa), se abre un formulario para rellenar los datos antes de generar el PDF fiscal.
  8. ** Reimprimir ticket**: botón para imprimir copia del ticket.

Paso 8: Mesa Liberada

Una vez cobrado:
- El pedido se marca como "Cerrado" en el backend.
- La mesa vuelve a estado ** Libre en el plano visual.
- Se muestra un
resumen rápido de la venta: "Mesa 3 cobrada: €32,00 en efectivo. "
- La mesa está lista para recibir nuevos clientes.


Funciones Avanzadas

5.1 Split Bill / Cuenta Dividida

Cuando un grupo de comensales quiere pagar por separado, el TPV permite dividir la cuenta.


   ←   Dividir Cuenta — Mesa 5     
   Total: €48,00                   


   Dividir por:                    

     1    2    3    4              ← Número de comensales




        COMENSAL 1               

        Hamburguesa   €12          ← Arrastrar productos
        Patatas        €4        
      Subtotal:       €16         

        COMENSAL 2               

        Pasta         €14        
        Vino tinto     €6        
      Subtotal:       €20         

        COMENSAL 3               

        Postre         €6        
        Cerveza        €4        
        Patatas (½)    €2          ← Producto dividido
      Subtotal:       €12         


   [  Añadir comensal]             


      COBRAR     COBRAR    COBRAR 
      €16        €20       €12    



Modo de división:
1. Por comensal: seleccionar número de comensales (1, 2, 3, 4...). El sistema crea bloques separados. El cajero puede arrastrar productos de la comanda general a cada comensal, o tocar un producto y asignarlo a un comensal.
2. Por producto: cada producto se asigna manualmente a un comensal.
3. División equitativa: botón para dividir el total a partes iguales automáticamente.
4. Producto dividido: un producto compartido (ej: patatas) puede dividirse en fracciones (½, ⅓) para cada comensal.

Cobro por comensal:
- Cada comensal tiene su propio botón de cobro con su subtotal.
- Al cobrar uno, se abre la pantalla de checkout normal pero solo con sus productos.
- Los comensales ya cobrados se marcan con . Los pendientes con ⏳.
- Pago mixto por comensal: cada comensal puede pagar su parte con método mixto (ej: €8 efectivo + €8 tarjeta).

Nota: El backend (TpvOrderController) registra cada cobro parcial como un partial_payment vinculado al mismo pedido. El pedido general se cierra cuando todos los comensales han pagado.

5.2 Hold Orders (Pedidos en Espera) ⏸

Cuando un cliente pide algo mientras decide, o cuando llega un grupo que aún no está listo para ordenar, el cajero puede guardar el pedido temporalmente.


     Pedido en espera              

   ¿Nombre o número para identificar?

      "Mesa 5 - Agua"            


   [Guardar]  [Cancelar]           


Flujo:
1. En la pantalla de comanda, el cajero toca el botón "⏸ Guardar en espera".
2. Aparece un modal pidiendo nombre o número para identificar el pedido (ej: "Mesa 5 - Agua", "Barra - Cerveza Juan", "Espera 1").
3. El pedido desaparece de la pantalla activa y se guarda en la lista de "En espera".
4. El cajero puede atender a otros clientes.
5. Recuperar: desde el tab principal o desde un botón dedicado, se accede a la lista de pedidos en espera:
```
PEDIDOS EN ESPERA

 ⏸  Mesa 5 - Agua         
    Hace 5 minutos        
    2 items

 ⏸  Barra - Cerveza Juan  
    Hace 12 minutos       
    1 item

 ⏸  Espera 3              
    Hace 1 hora           
    4 items

```
6. Al tocar un pedido en espera, se recupera completamente en la pantalla de comanda con todos los productos, mesa asignada y notas intactas.
7. Se puede eliminar un hold order si no se recupera.

Útil para: pedidos telefónicos que aún no se confirman, clientes que piden una ronda mientras deciden la comida, o cuando la mesa no está lista.

5.3 Mesas y Zonas

La gestión del plano del restaurante se realiza desde el módulo Mesas (o desde el Panel Admin para configuración avanzada).

Crear zonas (TableAreaController):


     Zonas del Restaurante         


       Terraza                   
     12 mesas                     

       Salón Principal           
     15 mesas                     

       Barra                     
     6 mesas                      

       Privado 1                 
     4 mesas                      


   [  Nueva zona]                 


  • Nueva zona: formulario con nombre (ej: "Terraza", "Salón", "Barra") y descripción opcional.
  • Las zonas aparecen como tabs en el plano de mesas.

Crear mesas:


     Nueva Mesa — Terraza          

   Número:     [ 13    ]           
   Capacidad:  [   ]         
   Posición:   [Fila 3, Col 4]     
   Forma:      [Cuadrada  ]        
   Activa:     [ ]                 

   [  Guardar]  [Cancelar]        

  • Número: identificador visual (1, 2, 3... o A1, B2...).
  • Capacidad: número de comensales (iconos de personas).
  • Posición: fila y columna en el grid visual del plano.
  • Forma: cuadrada, redonda, rectangular (afecta el icono visual).
  • Activa: si está desactivada, no aparece en el plano (útil para mesas rotas o en reforma).

Vista de plano:
- Grid visual responsive. En tablet se muestra más columnas; en móvil, menos.
- Cada mesa es una card con forma, número y estado de color.
- Toque largo (long press) en una mesa abre menú contextual: "Ver pedido", "Cambiar estado", "Editar", "Eliminar".

Unir mesas:
1. Tocar una mesa → "Seleccionar para unir".
2. Tocar una segunda mesa adyacente (o no adyacente, según configuración).
3. Botón "Unir mesas" aparece en la barra inferior.
4. Al confirmar, las dos mesas se muestran visualmente unidas (borde compartido, número combinado: "5+6").
5. Los pedidos de ambas mesas se fusionan en una sola comanda.
6. Se pueden desunir desde el menú contextual.

Cambiar mesa:
1. Desde el pedido activo, botón "↔ Cambiar mesa".
2. Se abre el plano de mesas. Las mesas libres aparecen en verde, las ocupadas en rojo (pero seleccionables para swap si se permite).
3. Tocar la mesa destino.
4. Confirmar. El pedido se mueve completamente a la nueva mesa. La mesa origen queda libre.

5.4 Menú del Día (Daily Menu)

El Menú del día es un producto especial con precio fijo y opciones configurables (DailyMenuController).

Configuración (desde Panel Admin o TPV):


     Configurar Menú del Día       
   Precio fijo: €15,00             

   Primer plato (elige 1):         
     Ensalada mixta               
     Sopa del día                 
     Gazpacho                     

   Segundo plato (elige 1):        
     Pollo al horno               
     Merluza a la plancha         
     Hamburguesa del chef         

   Postre (elige 1):               
     Flan                         
     Fruta del día                
     Helado                       

   Bebida (elige 1):               
     Agua                         
     Refresco                     
     Vino de la casa (copa)       

   [  Guardar configuración]      

En venta:
1. En la pantalla de menú, el producto "Menú del día" aparece como una card destacada (badge " Menú del día" o borde especial).
2. Al tocarlo, no aparece el bottom sheet normal. Aparece un wizard de pasos:
```
Paso 1/4: Primer plato

   Ensalada mixta         
   Sopa del día             ← Radio button
   Gazpacho

 [Siguiente →]

```
3. Paso 1: elegir primer plato. Paso 2: elegir segundo. Paso 3: postre. Paso 4: bebida.
4. Cada paso muestra las opciones configuradas como radio buttons (solo una selección por paso).
5. Al finalizar, se muestra un resumen de todas las elecciones y el precio fijo del menú.
6. Añadir al pedido. En la comanda aparece como una sola línea: "1x Menú del día (Sopa, Pollo, Flan, Agua) — €15,00".
7. En el ticket de cocina, se desglosa cada plato para que cocina lo prepare.

Nota: El precio fijo es invariable. Si el cliente quiere extras (ej: vino premium), se añade como producto aparte o como modificador con suplemento.

5.5 Escandallos / Recetas (TpvRecipeController)

El control de escandallos permite saber exactamente cuánto cuesta preparar cada plato y cuál es el margen de beneficio real.

Ficha de producto — Escandallo:


     Escandallo: Hamburguesa       

   INGREDIENTES:                   

     Pan brioche      1 u.        
     Carne 100%       150 g       
     Queso cheddar    30 g        
     Tomate           20 g        
     Lechuga          10 g        
     Salsa especial   15 ml       
     Patatas (guarn.) 100 g       


   COSTES:                         

     Coste materia prima:  €4,20     
     Coste mano de obra:  €1,50     
     Otros costes:       €0,80     

     COSTE TOTAL:       €6,50      
     PRECIO VENTA:      €12,00     

     MARGEN:            €5,50      
     MARGEN %:          45,8%      


     Margen mínimo configurado: 30%
     Margen actual está OK         

   [  Ver histórico de costes]      


Funcionalidades:
- Ingredientes: cada producto tiene una lista de ingredientes con cantidades y unidades (gramos, litros, unidades, mililitros).
- Coste unitario: precio de compra del ingrediente por unidad de medida (viene de TpvStockController).
- Coste total: suma automática de todos los ingredientes.
- Precio de venta: el precio actual configurado en el menú.
- Margen: precio de venta - coste total. Y margen porcentual: (margen / precio venta) × 100.
- Alerta de margen bajo: si el margen porcentual cae por debajo del mínimo configurado (ej: 30%), aparece una alerta roja en la ficha del producto y en el dashboard del TPV: "El margen de 'Hamburguesa' ha bajado al 22%. Revisa el precio de venta o los costes de ingredientes."
- Histórico de costes: gráfico de línea que muestra cómo ha evolucionado el coste de materia prima del producto en el tiempo (útil si los precios de proveedor suben).

Importante: El coste de materia prima se actualiza automáticamente cuando se registran entradas de stock con nuevos precios de compra. Si la carne sube de €8/kg a €10/kg, el coste del escandallo se recalcula automáticamente.

5.6 Grupos de Modificadores (TpvModifierGroupController)

Los modificadores permiten personalizar los productos sin crear variaciones infinitas en el menú.

Ejemplo: Hamburguesa Clásica

Modificadores configurados:

Grupo: "Cocción"
Tipo: Radio (solo 1)
• Poco hecho
• Al punto (por defecto)
• Muy hecho

Grupo: "Extras"
Tipo: Checkbox (varios)
• Doble queso        +€2,00
• Extra bacon        +€1,50
• Guacamole          +€1,00
• Huevo frito        +€1,50

Grupo: "Eliminar"
Tipo: Checkbox (varios)
• Sin cebolla        €0,00
• Sin tomate         €0,00
• Sin salsa          €0,00

Grupo: "Acompañamiento"
Tipo: Radio (solo 1)
• Patatas fritas (incluido)
• Patatas gajo       +€1,00
• Ensalada           +€0,50

Configuración (desde Panel Admin):
- Grupo de modificadores: nombre, tipo de selección (radio = 1 opción; checkbox = múltiples), obligatorio o opcional.
- Opciones: nombre, precio adicional (puede ser €0,00), icono opcional.
- Asignar a productos: se asigna el grupo a uno o varios productos. Ej: el grupo "Extras" puede servir para hamburguesas, sandwiches y wraps.

En venta (bottom sheet):
- Los grupos aparecen como secciones separadas en el bottom sheet del producto.
- Radio buttons circulares para selección única.
- Checkboxes cuadrados para selección múltiple.
- Precio adicional se muestra en gris a la derecha de cada opción (ej: "+€2,00").
- El total del bottom sheet se actualiza en tiempo real al marcar/desmarcar opciones.

5.7 Ofertas (TpvOfferController)

Las ofertas se aplican automáticamente al crear el pedido si se cumplen las condiciones, o manualmente con un código.

Tipos de ofertas configurables:

Tipo Descripción Ejemplo visual en comanda
2x1 Compra 1, el segundo igual gratis 2x Hamburguesa €12,00 → Total €12,00 (descuento -€12,00)
Descuento % Porcentaje sobre producto o total Descuento 20%: -€6,40
Descuento fijo Cantidad fija de descuento -€5,00
Combo Productos combinados a precio especial Menú burger + bebida + postre = €15,00 (ahorras €3,50)
Happy Hour Descuento por horario (tarifas) De 17:00 a 19:00: cerveza -30%
Cupón Código manual Código "VERANO25": -25%

Configuración:
- Condiciones: productos incluidos, categorías, horario válido, días de la semana, mínimo de compra.
- Límite de uso: máximo por día, por cliente, por sesión.
- Acumulable: si puede combinarse con otras ofertas.

En venta:
- Las ofertas activas se muestran como badges en los productos afectados (ej: " 2x1" en rojo).
- Al añadir productos que cumplen la oferta, aparece un toast informativo: "¡Oferta 2x1 aplicada! Ahorraste €12,00 "
- En la comanda, el descuento aparece como línea separada con nombre de la oferta y monto.
- El total se actualiza automáticamente.

5.8 Stock / Almacén (TpvStockController)

El control de stock es fundamental para evitar quedarse sin productos o para controlar costes.

Movimientos de stock:


     Movimiento de Stock           

   Tipo: [Entrada  ]               
   Producto: [Buscar...]   Carne   
   Cantidad: [  50  ] kg           
   Proveedor: [Carnicería López]     
   Precio unitario: [€8,50]        
   Total: €425,00                  
   Nota: [Pedido semanal]          

   [  Registrar entrada]           

Tipos de movimiento:
- ** Entrada: compra a proveedor, recepción de mercancía. Aumenta el stock y actualiza el coste promedio ponderado.
- ** Salida
: consumo por ventas (automático vía StockReservationService cuando se envía a cocina), merma, rotura, uso interno.
- ** Ajuste: corrección tras inventario físico. Puede ser positivo (se encontró más) o negativo (se perdió).
-
↩ Devolución**: devolución a proveedor (entrada negativa).

Reserva de stock automática:
- Cuando se crea un pedido y se envía a cocina, el backend (StockReservationService) reserva automáticamente los ingredientes necesarios según el escandallo del producto.
- Ej: si vendes 1 hamburguesa, se reservan 150g de carne, 1 pan, 30g de queso, etc.
- El stock disponible se reduce en tiempo real.
- Si el stock es insuficiente, aparece una alerta en la pantalla del producto: "Stock bajo: solo quedan 2 raciones disponibles".

Inventario físico:


     Inventario — 20/06/2026       

   Producto          Sistema  Real  

     Carne (kg)      45,50   [45] 
     Queso (kg)      12,30   [12] 
     Tomate (kg)      8,00   [8]  
     Lechuga (u.)     25      [24] 

   [  Guardar ajustes]             
   Diferencias: 4 productos         
   Ajuste total: -€12,50           


  • Lista de todos los productos con stock.
  • Columna "Sistema": cantidad que el sistema cree que hay (según entradas, salidas y ventas).
  • Columna "Real": campo editable donde el cajero/jefe de almacén introduce el conteo físico real.
  • Al guardar, se generan ajustes automáticos para corregir las diferencias.
  • Se puede imprimir o exportar el informe de inventario.

Alertas de stock bajo:


     Alertas de Stock              

       Carne (kg)                 
     Mínimo: 20 | Actual: 8        
     ¡Reponer urgentemente!         

       Queso (kg)                 
     Mínimo: 10 | Actual: 9        
     Próximo al mínimo              

       Cerveza (u.)                
     Mínimo: 50 | Actual: 45       
     Próximo al mínimo              

   [  Enviar pedido a proveedor]   


  • Cada producto tiene un stock mínimo configurable.
  • Cuando el stock actual baja del mínimo, aparece en la lista de alertas.
  • ** Rojo**: stock crítico (0 o muy cerca de 0).
  • ** Amarillo**: stock bajo (por debajo del mínimo pero aún disponible).
  • El badge de alertas en la barra superior muestra el número de productos con stock bajo.

5.9 Clientes TPV (TpvCustomerController)

El módulo de clientes permite gestionar la base de datos de clientes para fidelización, pedidos telefónicos y facturación.

Nuevo cliente:


     Nuevo Cliente                 

   Nombre:    [María García]       
   Teléfono:  [612 345 678]        
   Email:     [maria@email.com]    
   Dirección: [C/ Mayor 15, 3ºB]   
   Notas:     [Alérgica a marisco] 

   Alérgenos:                      
     Mariscos     Frutos secos    
     Gluten        Lácteos         
     Huevo         Soja            

   [  Guardar cliente]              


  • Nombre completo: obligatorio.
  • Teléfono: clave primaria para búsqueda rápida. Único en el sistema.
  • Email: para envío de facturas y comunicaciones.
  • Dirección: útil para delivery o para notas de envío.
  • Notas: campo libre para alergias, preferencias, cumpleaños, etc.
  • Alérgenos: checklist con los 14 alérgenos principales del reglamento europeo (gluten, crustáceos, huevos, pescado, cacahuetes, soja, lácteos, frutos de cáscara, apio, mostaza, sésamo, sulfitos, altramuces, moluscos). Estos se muestran en alerta al tomar pedidos para ese cliente.

Búsqueda rápida:
- Desde la pantalla de checkout o desde el módulo Clientes, hay un teclado numérico dedicado para buscar por teléfono.
- Al teclear 3 o más dígitos, aparece lista de coincidencias.
- También se puede buscar por nombre (teclado alfabético) o por email.

Historial de compras:


     María García                  
     612 345 678                   

     ÚLTIMOS PEDIDOS:             

     20/06  Mesa 5    €32,00      
     18/06  Para llevar €15,00     
     15/06  Mesa 3    €28,50      
     10/06  Mesa 8    €45,00      
     02/06  Mesa 2    €22,00      


     PRODUCTOS FAVORITOS:          
   1.   Hamburguesa Clásica (x4)  
   2.   Coca-Cola (x5)            
   3.   Tarta de queso (x3)      

     Frecuencia: 2,3 visitas/mes  
     Gasto medio: €28,50          

     FIDELIDAD:                   
   Puntos acumulados: 145 pts      
   Wallet interno: €5,00           
   [Canjear puntos]                


  • Últimos 5 pedidos: fecha, tipo (mesa/para llevar), total.
  • Productos favoritos: productos más pedidos por este cliente, con contador de frecuencia.
  • Frecuencia: visitas promedio por mes.
  • Gasto medio: ticket promedio del cliente.

Fidelidad:
- Puntos: cada compra acumula puntos según configuración (ej: 1 punto por cada € gastado). Los puntos se pueden canjear por descuentos o productos gratuitos.
- Wallet interno: saldo de prepago o bonus que el cliente tiene en su cuenta. Se puede usar como método de pago en checkout.
- Canjear puntos: desde el checkout, si el cliente tiene suficientes puntos, aparece opción "Canjear 100 pts = -€5,00".

5.10 Impresoras y Periféricos (TpvPrinterController, TpvPeripheralController)

La configuración de impresoras es clave para el flujo de cocina y caja.

Configurar impresora:


     Impresoras                    


       Cocina (Red)              
     IP: 192.168.1.105            
     Estado:   Conectada         
     Modelo: Epson TM-T20          

       Barra (Bluetooth)         
     MAC: XX:XX:XX:XX:XX:XX       
     Estado:   Emparejada        
     Modelo: Bixolon SPP-R200     

       Caja (Red)                
     IP: 192.168.1.106            
     Estado:   Desconectada      
     [Reconectar]                  


   [  Añadir impresora]            


Añadir impresora:
1. Bluetooth: la app escanea dispositivos Bluetooth cercanos. Seleccionar la impresora térmica de la lista, emparejar (puede requerir PIN 0000 o 1234).
2. Red (WiFi/Ethernet): introducir IP del servidor de impresión o de la impresora directamente (si es red). Puerto por defecto 9100.
3. Asignar categorías: seleccionar qué categorías de productos imprime cada impresora. Ej: Cocina imprime Hamburguesas, Pastas; Barra imprime Bebidas, Postres; Caja imprime todos los tickets de cobro.
4. Imprimir ticket de prueba: botón que envía un ticket de prueba con texto de diagnóstico para verificar conexión.

Ticket layout:


     Diseño del Ticket             

   Logo: [  Subir imagen]         
   Previsualización:               

        [LOGO]                    
      RESTAURANTE ZEUMAX         
      C/ Mayor 15, Madrid         
      NIF: B-12345678             

      TICKET #000145              
      20/06/2026 14:32            

      1x Hamburguesa  €12,00      
      2x Patatas       €8,00      

      SUBTOTAL:       €20,00      
      IVA 10%:         €2,00      
      TOTAL:          €22,00      

      Pago: Efectivo              
      Cambio:          €3,00      

      ¡Gracias por su visita!     
      ZEUMAX         


   Pie de ticket:                  
   [¡Gracias por su visita!]       

   Tamaño letra: [Normal  ]        
   Ancho ticket: [58mm  ]          

   [  Guardar diseño]              


  • Logo: subir imagen desde galería. Se recomienda blanco y negro, 300px de ancho máximo.
  • Info legal: dirección, NIF, teléfono — configurable.
  • Pie de ticket: mensaje personalizado ("¡Gracias! Síguenos en @zeumax").
  • Tamaño de letra: Normal, Grande, Pequeño (para personas mayores o visibilidad).
  • Ancho de ticket: 58mm (típico) o 80mm (impresoras grandes).

Periféricos:
- Cajón de dinero (CashDro): conectado por Bluetooth o por cable a la impresora de caja. Se abre automáticamente al cobrar en efectivo. También se puede abrir manualmente con botón "Abrir cajón" en la barra superior.
- Pantalla cliente: configurar IP/puerto del visualizador. Se envía el total a mostrar en tiempo real durante el checkout.
- Buzzer/llamador: opcional, para llamar a mesa cuando el pedido está listo.

5.11 Turnos y Fichaje (TpvShiftController, TpvAttendanceController) ⏰

La gestión de turnos y fichaje permite controlar las horas trabajadas por los empleados.

Definir turnos:


     Turnos de Trabajo             


       Mañana                    
     08:00 - 16:00                
     Lunes a Viernes              

       Tarde                     
     16:00 - 23:00                
     Lunes a Sábado               

       Noche                     
     23:00 - 08:00                
     Viernes y Sábado             


   [  Nuevo turno]                 


  • Cada turno tiene nombre, hora inicio, hora fin, y días de la semana aplicables.
  • El sistema puede sugerir automáticamente el turno actual según la hora del día.

Fichaje (Clock-in / Clock-out):


     Fichaje — Carlos M.           
     20/06/2026                   

   Turno actual:   Mañana          
   Horario: 08:00 - 16:00          

   Estado:   NO FICHADO           


        FICHAR ENTRADA           
          08:02                   



   HISTORIAL DE HOY:               
   Entrada: --:--                
   Salida:  --:--                
   Horas:    0h 00m              


  • Fichar entrada: botón verde grande. Al tocar, registra la hora actual. Cambia estado a "Trabajando".
  • Fichar salida: cuando el estado es "Trabajando", el botón cambia a "FICHAR SALIDA". Al tocar, registra hora de salida y calcula horas trabajadas.
  • Horas trabajadas: se muestra en tiempo real mientras está fichado.
  • Resumen semanal: accesible desde el tab de informes. Muestra tabla con días de la semana, entrada, salida, horas, y total semanal.
  • Alerta: si un empleado intenta iniciar una sesión de caja sin haber fichado entrada, aparece advertencia (configurable).

Nota: El fichaje se registra en el backend (TpvAttendanceController) y puede exportarse a CSV para nómina.

5.12 Festivos y Calendario (TpvHolidayController)

Permite marcar los días en que el restaurante estará cerrado.


     Festivos y Cierre             
   Junio 2026                      

   Lu Ma Mi Ju Vi Sa Do           

   1  2  3  4  5  6  7            
   8  9  10 11 12 13 14           
   15 16 17 18 19 20 21           
   22 23 24 25 26 27 28           
   29 30                          

     Abierto    Cerrado    Festivo

   Días marcados:                  
   • 24/06: San Juan (festivo)    
   • 25/06: Cerrado por vacaciones 
   • 26/06: Cerrado por vacaciones 

   [  Añadir festivo]              


Funcionalidades:
- Calendario mensual: visual claro con días marcados en colores.
- Añadir festivo: formulario con fecha, tipo (festivo nacional, vacaciones, cierre temporal, reforma), y nota.
- Repetición anual: opción de repetir el festivo todos los años (ej: Navidad 25/12, Año Nuevo 1/1).
- Bloqueo de ventas: en un día marcado como cerrado, el TPV no permite crear nuevos pedidos. Aparece modal: "El restaurante está cerrado hoy (Vacaciones). Contacta con el administrador."
- Los pedidos programados (reservas) para días cerrados se muestran en alerta para reprogramación o cancelación.

5.13 Alertas y Perfil TPV (TpvAlertController, TpvProfileController)

Alertas del sistema:


     Alertas (3)                   

     Stock bajo                    
     Carne (kg): 8 (mín: 20)     
   [Ir a stock]                     

     Impresora desconectada       
   Caja (192.168.1.106) sin respuesta 
   [Reconectar]                    

     Sesión por expirar           
   Tu sesión de caja lleva 10h     
   activa. Considera cerrar.      
   [Cerrar caja]                   


Tipos de alertas:
- ** Crítica: stock bajo, impresora desconectada, error de sincronización, caja sin abrir. Requieren acción inmediata. Hacen sonido y vibración.
- ** Advertencia
: sesión por expirar, stock próximo al mínimo, cliente con alergia en pedido actual, pedido en hold desde hace mucho tiempo.
- ** Informativa**: pedido listo en cocina, backup completado, actualización disponible.

El badge de la campana en la barra superior muestra el número de alertas no leídas. Al tocar, se abre la lista.

Perfil TPV:


     Perfil TPV — Carlos M.        

   Nombre: Carlos Martínez         
   Rol: Cajero / Encargado         

   Cambiar PIN: [••••••]           
   [Guardar PIN]                    

   Preferencias:                   
   Impresora preferida: [Caja  ]  
   Tema: [Claro  ]                 
   Sonido de alertas: [ ]         
   Vibración: [ ]                 
   Tamaño de letra: [Normal  ]     

   [  Guardar preferencias]        

   [  Cerrar sesión]               

  • Cambiar PIN: el usuario puede cambiar su PIN TPV (valida el actual primero).
  • Impresora preferida: seleccionar impresora por defecto para reimpresiones rápidas.
  • Tema: claro (por defecto) u oscuro (para uso nocturno).
  • Sonido/Vibración: configuración de notificaciones táctiles.
  • Tamaño de letra: accesibilidad para usuarios con dificultades de visión.

5.14 Informes (TpvReportController)

El módulo de informes permite al cajero o encargado consultar datos de ventas sin necesidad del Panel Admin.


     Informes de Ventas            

   Período: [Hoy  ]                

    Hoy  Ayer Sem.  Mes            

   o [Personalizado: __/__/__]       

   RESUMEN:                        

     Ventas totales: €1.245,00     
     Tickets: 42                    
     Ticket medio: €29,64          
     Productos vendidos: 156        
     Clientes atendidos: 38         
     Hora pico: 14:00-15:00         


   TIPO DE INFORME:                
   [Ventas por producto]           
   [Ventas por categoría]         
   [Ventas por método de pago]    
   [Ventas por empleado]           
   [Ventas por hora]               

   [  Exportar CSV]                


Ventas por producto:

Ranking de productos — Hoy

  #  Producto          Cant  €     
  1    Hamburguesa     24  €288   
  2    Patatas          31  €186   
  3    Coca-Cola        45  €112   
  4    Pizza Margarita  12  €168   
  5    Ensalada César   15  €135   
  ...                               

  • Lista ordenada por cantidad vendida o por ingresos.
  • Indica tendencia respecto al día anterior (flecha ↑ ↓).

Ventas por categoría:

Gráfico circular (pie chart):
  Comidas: 62%  (€771)
  Bebidas: 28%  (€349)
  Postres: 10%  (€125)

Ventas por método de pago:

  Efectivo: 45%  (€560)
  Tarjeta:   48%  (€598)
  Wallet:    7%   (€87)

Ventas por empleado:


  Carlos M.  18 tickets  €534     
  Ana R.     15 tickets  €445     
  Luis G.     9 tickets  €266     

  • Muestra tickets atendidos y total vendido por cada cajero.
  • Útil para comisiones o evaluación de rendimiento.

Ventas por hora:

Gráfico de barras (bar chart):
08:    €45
09:    €20
10:    €78
11:    €134
12:    €245
13:    €356
14:    €412  ← Pico
15:    €267
16:    €156
...
  • Muestra volumen de ventas por hora del día.
  • Útil para planificar turnos de personal (más cajeros en hora pico).

Exportar:
- Botón "Exportar CSV" genera archivo CSV compatible con Excel.
- El archivo incluye todas las líneas de venta del período: fecha, hora, producto, cantidad, precio, empleado, método de pago, mesa.
- Se puede compartir por email o guardar en el dispositivo.


Cierre de Caja

Al final del turno, el cajero debe realizar el cierre de caja para cuadrar las ventas con el efectivo real.


     Cierre de Caja                
   Sesión: #142 — Carlos M.       
   Apertura: 08:00  20/06/2026    
   Cierre:  16:00  20/06/2026     


        EFECTIVO                 
      Fondo inicial:  €100,00     
      Ventas efectivo: €560,00     
      Movimientos:     -€20,00       (retirada)

      Sistema:       €640,00     
      Real contado: [€638,00]        ← Teclado numérico

      DIFERENCIA:     -€2,00          Faltante



        TARJETAS                 
      Ventas tarjeta: €598,00     
      Datáfono:     €598,00       
      Diferencia:     €0,00            OK



        VOUCHERS/WALLET          
      Ventas wallet:   €87,00     
      Diferencia:      €0,00          OK


   RESUMEN DE VENTAS:              
   Total tickets: 42               
   Ticket medio: €29,64            
   Total ventas: €1.245,00       
   Productos más vendidos:         
   1. Hamburguesa (24)           
   2. Patatas (31)                 
   3. Coca-Cola (45)               


        CONFIRMAR CIERRE         
      E imprimir resumen          


   [  Cancelar]                    


Flujo de cierre:
1. Conteo de efectivo: el cajero cuenta físicamente todas las monedas y billetes en la caja. Introduce el total en el campo "Real contado".
2. Diferencia: el sistema calcula automáticamente la diferencia entre lo que debería haber (fondo inicial + ventas efectivo + movimientos de caja) y lo que realmente hay.
- ** Sobrante: hay más dinero de lo esperado (+€X,XX).
- ** Faltante
: hay menos dinero de lo esperado (-€X,XX).
- ** OK: cuadra exactamente (€0,00).
3.
Tarjetas: se compara el total de ventas por tarjeta con el cierre del datáfono (si está integrado) o se introduce manualmente.
4.
Vouchers/Wallet: total de ventas con métodos no físicos.
5.
Resumen de ventas: tickets totales, ticket medio, total de ventas, top 3 productos.
6.
Confirmar cierre: al tocar el botón verde o rojo según la acción, se registra el cierre en el backend (TpvSessionController). Se genera un ticket de cierre que se imprime automáticamente (resumen completo del turno).
7.
Logout automático**: tras cerrar la caja, la sesión TPV se cierra y vuelve a la pantalla de login.

Nota sobre movimientos de caja: Durante el turno, el cajero puede haber realizado movimientos de caja (entrada/salida de efectivo): retirada para caja menor, ingreso de cambio, ajuste de conteo. Estos movimientos se reflejan en el cierre. Se explican en el flujo de venta principal como parte de la operación diaria.


Solución de Problemas Comunes

"No se conecta la impresora"

Síntoma Causa probable Solución
"Impresora no encontrada" Bluetooth apagado o no emparejada Verificar que la impresora esté encendida y en modo emparejamiento. Ir a Ajustes > Impresoras > Añadir impresora > Bluetooth. Emparejar de nuevo.
"Error de conexión red" IP incorrecta o impresora apagada Verificar que la impresora de red esté encendida. Comprobar la IP en la configuración. Hacer ping desde otro dispositivo.
"Ticket no se imprime" Papel agotado o atascado Abrir la impresora, verificar que haya papel térmico (rollo de 58mm o 80mm). Revisar si el papel está atascado.
"Impresión borrosa" Cabezal sucio o papel de mala calidad Limpiar el cabezal térmico con alcohol isopropílico. Usar papel térmico de buena calidad.
"Batería baja" Impresora Bluetooth sin carga Conectar la impresora a su cargador. Algunas modelos no imprimen con batería crítica.

Consejo: Siempre mantener un rollo de papel de repuesto cerca del TPV. La app muestra un warning cuando detecta que la impresora no respondió a la última impresión (aunque no siempre puede detectar falta de papel).

"No puedo enviar a cocina"

Síntoma Causa probable Solución
"No hay sesión abierta" Caja no fue abierta al inicio Ir a la pantalla de inicio y realizar Apertura de caja con el fondo inicial.
"No hay impresora configurada" No se asignó impresora para la categoría Ir a Ajustes > Impresoras > Añadir impresora. Asignar la impresora a la categoría de los productos (ej: Cocina para hamburguesas).
"Error al enviar pedido" Conexión a internet caída Verificar conexión WiFi o datos móviles. El TPV requiere internet para sincronizar con el backend.
"Pedido enviado pero no llega a cocina" Impresora de cocina desconectada Revisar estado de la impresora en Ajustes > Impresoras. Intentar reconectar o imprimir ticket de prueba.

"Pedido no aparece"

Síntoma Causa probable Solución
"No veo el pedido en la lista" Está en estado "Hold" Revisar la lista de Pedidos en espera desde el tab principal. Recuperar el pedido.
"La mesa parece libre pero debería estar ocupada" Pedido asignado a otra mesa Verificar el número de mesa en el pedido. Usar Cambiar mesa si fue asignado incorrectamente.
"No aparece en informes" El pedido está pendiente de cobro Los pedidos no cobrados no aparecen en informes de ventas. Ir a checkout y completar el pago.
"Filtros activos" Se aplicó un filtro que oculta el pedido Revisar si hay filtros de fecha, zona o empleado activos en la pantalla de pedidos. Limpiar filtros.

"Stock negativo o incorrecto"

Síntoma Causa probable Solución
"Stock muestra -5" Ventas superaron las entradas Revisar el escandallo del producto. Si el coste es correcto, hacer una entrada de stock para reponer. Si fue un error de venta, cancelar el pedido que causó el consumo.
"Stock del sistema no coincide con el real" Mermas, roturas o robos no registrados Realizar un inventario físico desde el módulo Stock. Introducir el conteo real y generar ajustes.
"Producto aparece sin stock pero hay en almacén" No se registró la entrada de compra Registrar la entrada de stock desde el proveedor con cantidad y precio.
"Alerta de stock bajo constante" Stock mínimo configurado muy alto Ajustar el stock mínimo del producto desde el Panel Admin o desde la ficha de stock.

Otros problemas frecuentes

Problema Solución
App se bloquea o va lenta Cerrar otras apps en el dispositivo. Reiniciar el TPV. Si persiste, verificar espacio de almacenamiento libre.
PIN no funciona Verificar que el teclado numérico esté respondiendo. Si el PIN fue olvidado, contactar al administrador para reset desde Panel Admin.
No sincroniza con el backend Verificar conexión a internet. Si hay proxy o firewall corporativo, verificar que los puertos del backend estén abiertos.
Cliente no aparece en búsqueda Asegurarse de que el número de teléfono fue guardado correctamente (sin espacios ni prefijos extraños). Buscar por nombre como alternativa.
Cupón no se aplica Verificar que el cupón no haya expirado, que el pedido cumpla el mínimo de compra, y que no se haya excedido el límite de usos.
Cambio de mesa falla Asegurarse de que la mesa destino esté libre (o configurar para permitir swap). Si hay pedido en la mesa destino, unir mesas en lugar de cambiar.

Conclusión y Buenas Prácticas

El TPV de ZEUMAX es una herramienta potente y completa que centraliza toda la operación de caja de tu restaurante. Para obtener el máximo rendimiento:

  1. ** Siempre abre la caja al inicio del turno**. Sin sesión abierta, no se puede operar.
  2. ** Verifica las impresoras al inicio**. Imprime un ticket de prueba para confirmar que todo está conectado antes de que lleguen los clientes.
  3. ** Usa las notas en los pedidos**. Indicar "alérgeno", "poco hecho" o "cumpleaños" evita errores de cocina y mejora la experiencia del cliente.
  4. ⏸ Usa Hold Orders para mesas indecisas. No pierdas el pedido parcial si el cliente necesita más tiempo.
  5. ** Revisa los informes al finalizar**. El resumen de ventas por hora te ayuda a planificar mejor los turnos de personal.
  6. ** Cierra la caja cuadrando**. El conteo físico debe coincidir con el sistema. Una diferencia recurrente indica un problema que debe investigarse.
  7. ** Mantén el stock actualizado**. Registra las entradas de compra y haz inventarios periódicos para que los escandallos y alertas sean precisos.
  8. ** Fideliza a tus clientes**. Registra clientes habituales, usa puntos de fidelidad y envía facturas por email para una experiencia profesional.

Documento: 06-tpv.md
Sistema: ZEUMAX (ZEUMAX)
Módulo: TPV (Terminal Punto de Venta)
Tecnología: React Native + Expo + NativeWind + Zustand + MMKV
Backend: API del sistema (controladores de sesión, pedidos, stock, etc.)
Auth Guard: auth:tpv_api
Middleware: CheckTpvFeature
Paleta: Brand #8BC34A | TopMenuBar #424242
Estado: Documento de referencia para el manual de usuario del cajero.


¿Necesitas más detalle sobre algún submódulo específico? Consulta los documentos adicionales del manual o contacta al administrador del sistema.