feat(F-186): completed feature
This commit is contained in:
144
docs/pos/POS_CHECKOUT.md
Normal file
144
docs/pos/POS_CHECKOUT.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# 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
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
```json
|
||||
{
|
||||
"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`
|
||||
|
||||
```json
|
||||
{ "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.
|
||||
Reference in New Issue
Block a user