Files
mercadodevida/docs/pos/POS_CHECKOUT.md
2026-08-22 22:08:30 +02:00

4.7 KiB

TPV — Checkout, pagos mixtos y tickets

Implementado en F-186. Complementa POS_API.md y sustituye el flujo inmediato de pago único descrito en documentos de discovery antiguos.

Configuración en administración

En Administración → TPV, selecciona una tienda para configurar:

Terminal

  • Navegación táctil por categorías.
  • Hasta ocho productos rápidos por terminal.
  • Permitir descuentos por línea. Desactívalo en terminales de autopago. La restricción se aplica también en backend, no solo ocultando el botón.

Formas de pago

Cada tienda puede activar o desactivar métodos con:

  • código estable (cash, card, bizum, stripe, apple_pay, etc.);
  • etiqueta visible;
  • tipo cash, card u other.

Una etiqueta no integra automáticamente una pasarela. Stripe, Apple Pay, Bizum u otros métodos se registran manualmente hasta que exista un adaptador de proveedor.

Empresa y ticket

Configura:

  • nombre o razón social;
  • NIF/CIF;
  • dirección, teléfono y email;
  • cabecera y pie;
  • prefijo, próximo número y dígitos de relleno;
  • política de devolución.

La asignación del siguiente número se bloquea dentro de la transacción de venta, evitando números duplicados entre terminales concurrentes.

Flujo de caja

  1. Añade productos de catálogo o un Artículo libre (nombre y precio positivo).
  2. Aplica descuentos por línea si el terminal los permite.
  3. Pulsa una forma de pago configurada.
  4. En el modal elige:
    • Paga el total: asigna todo el importe pendiente.
    • Paga una parte: introduce un importe menor y añade después otro método.
  5. En efectivo, indica lo entregado. El TPV muestra el cambio.
  6. Revisa las líneas de pago, el total pagado y el importe pendiente. Se puede quitar una asignación antes de confirmar.
  7. Cuando el pendiente sea cero, pulsa Confirmar y cerrar ticket.
  8. Imprime o envía el ticket por email. La caja se limpia después de completar una de estas acciones.

Una venta totalmente pagada queda en estado COMPLETED. Los pagos pendientes se implementan aparte en F-188.

Contrato de venta

POST /pos/sales

Línea de stock

{
  "kind": "stock",
  "variantId": "uuid",
  "quantity": 2,
  "discountCents": 100
}

El backend ignora snapshots antiguos enviados por el cliente y vuelve a cargar nombre, SKU, EAN y precio. También bloquea y actualiza el stock de la tienda.

Artículo libre

{
  "kind": "free",
  "name": "Servicio de asesoría",
  "unitPriceCents": 2500,
  "quantity": 1
}

No reserva ni descuenta inventario. La base de datos exige que product_id y variant_id sean nulos únicamente en estas líneas.

Pago

{
  "methodCode": "cash",
  "amountCents": 1000,
  "tenderedCents": 2000
}
  • La suma de amountCents debe coincidir exactamente con el total.
  • Solo un método de tipo efectivo acepta tenderedCents.
  • tenderedCents debe ser mayor o igual que el importe aplicado.
  • El cambio es tenderedCents - amountCents.
  • Un código inactivo o de otra tienda se rechaza.

La venta, stock, pagos, líneas de reporting, saldo esperado de caja, número y ticket se confirman en una única transacción idempotente.

Ticket

La respuesta de venta y GET /pos/sales/:id/receipt contienen:

  • datos de empresa;
  • fecha y hora;
  • número de ticket;
  • terminal, sesión y cajero;
  • artículos, cantidad, precio, subtotal, descuento, IVA y total de línea;
  • subtotal, descuentos, IVA y total de venta;
  • métodos e importes pagados;
  • efectivo entregado y cambio;
  • política de devolución.

Impresión

GET /pos/sales/:id/print devuelve el mismo payload estructurado. El cliente usa impresión estándar del navegador, sin controlador específico de hardware.

Email

POST /pos/sales/:id/receipt/email

{ "email": "cliente@example.es" }

Usa la configuración SMTP de Ajustes → SMTP / Email. El asunto y contenido se generan exclusivamente desde el ticket; el cliente no puede suministrar HTML arbitrario.

Reporting y caja

Por cada asignación se crea:

  • una transacción en payments_transactions;
  • una línea payment en reporting_payment_lines con tienda, terminal, sesión y método.

El efectivo esperado aumenta por el importe aplicado, no por el efectivo entregado; el cambio no cuenta como ingreso ni efectivo retenido.

Próximas ampliaciones

  • F-187: eliminar/desactivar cajeros preservando histórico.
  • F-188: ventas con saldo pendiente.
  • F-189: cantidades negativas, devoluciones parciales/totales y ticket de devolución.
  • F-190: auditoría completa de actualización/refresco de reporting.
  • F-191: cierre de terminal y cierre diario conciliando efectivo, tarjetas, devoluciones y pendientes.