# Actualización v1.3.0

## Aplicar sobre v1.2

1. Respalda base de datos y `.env`, incluida la APP_KEY. Reemplaza los archivos del backend y `vendor` con los del ZIP; conserva `.env` y el contenido propio de `storage`.
2. En Windows ejecuta `ACTUALIZAR.bat`. En Linux: `php artisan optimize:clear` y `php artisan migrate --seed --force`. No ejecutes migrate:fresh ni vuelvas a generar APP_KEY en una instalación existente.
3. Actualiza el frontend completo y recompila con tu VITE_API_URL: `npm ci` y `npm run build`. Publica el contenido de `dist`, incluida la carpeta `denominaciones`.

Puertos de desarrollo: API 8016; frontend 5184. Se incluyen dependencias PHP de producción y frontend compilado para localhost:8016. La aplicación no incluye credenciales reales ni cuentas de acceso precreadas; los tests contienen fixtures ficticios aislados.

## QR: configuración

Configuración → Cobros QR → proveedor → modo Pruebas o Producción. Los datos vacíos conservan las claves ya configuradas. Guarda y pulsa Probar conexión; esta prueba solicita autenticación, no genera un cobro. Solo administradores pueden guardar y probar los accesos. La respuesta del servidor indica qué campos están configurados y nunca devuelve sus valores.

| Proveedor | Pruebas | Producción | Datos |
|---|---|---|---|
| BNB | http://test.bnb.com.bo | https://marketapi.bnb.com.bo | Account ID, Authorization ID, cuenta destino |
| SIP | http://dev-sip.mc4.com.bo:8443 | https://sip.mc4.com.bo:8443 | Usuario, contraseña, API key empresa, API key servicio, usuario y contraseña del callback |

La documentación BNB adjunta contiene accountId/authorizationId en la descripción y username/password en un ejemplo. El selector de contrato permite usar el formato asignado por BNB con los mismos dos campos de acceso. Debe validarse con credenciales de pruebas antes de pasar a producción.

En SIP, la llave de servicio determina la cuenta y el banco receptor. El rótulo BMSC/BISA/Banco Económico es una referencia para el operador: no cambia el contrato de la API. Se configura una cuenta de servicio por ambiente; solo un ambiente de cada proveedor puede quedar habilitado. Los intentos ya creados conservan cifrada su conexión original para consultar el ambiente y la cuenta correctos aunque después cambies el panel.

Para SIP registra con el proveedor el callback `APP_URL/api/v1/qr/callback/sip`, con HTTP Basic y los mismos datos guardados en el panel. Contraseña del callback: mínimo 12 caracteres con mayúscula, minúscula y símbolo. En producción APP_URL debe ser pública y HTTPS. El callback comprueba autenticación y vuelve a consultar al proveedor; no acepta un campo enviado por el navegador como prueba de pago.

## Cobrar y confirmar

- En el POS selecciona QR dinámico y el proveedor habilitado. En esta versión el QR cubre el total: no se combina con efectivo u otro medio dentro de la misma venta.
- Se validan productos, revisión de receta y disponibilidad; se reservan unidades por lote. Todavía no se crea la venta ni se descuenta el stock físico. El catálogo descuenta lo reservado del stock disponible.
- El QR es de un solo uso, en BOB, con vencimiento en la fecha de generación, conforme al contrato de fecha de los proveedores.
- El modal consulta cada 8 segundos durante hasta 60 consultas; después permite continuar manualmente. Puedes descargar la imagen PNG o retomar el intento desde Cobros QR.
- Con confirmación automática, al comprobar el pago se registra una sola venta y su cobro QR. Con confirmación manual, el pago queda verificado y el operador pulsa Confirmar venta. Esa acción también exige verificación bancaria; no hay botón para declarar arbitrariamente que llegó el dinero.
- Si llega el pago y el producto/lote quedó bloqueado, vencido o no cumple la revisión sanitaria, queda en Revisar. Se conserva el pago y la reserva; corrige la causa y confirma nuevamente desde Cobros QR. Nunca se simula una venta exitosa.
- Un timeout al generar conserva el mismo intento y las reservas; no genera otro QR automáticamente. BNB intenta recuperar el ID por alias, fecha, importe y moneda; SIP consulta por alias. Si no hay coincidencia inequívoca, requiere conciliación con el proveedor.
- Las reservas se liberan al vender, ante rechazo confirmado de generación, vencimiento bancario o anulación aceptada por el proveedor. El reloj local por sí solo no libera una reserva.
- Debes resolver los intentos pendientes antes de cerrar la caja. Los QR confirmados aparecen separados de efectivo y transferencia en el cierre.
- La anulación de una venta ya pagada conserva el procedimiento de caja existente. **No ejecuta una devolución bancaria automática.** La devolución de dinero debe gestionarse y verificarse por separado con el banco.

## Consulta automática en servidor

Para confirmar aunque el operador cierre el navegador, activa el planificador de Laravel en el servidor. Ejemplo de cron, ajustando la ruta:

```cron
* * * * * cd /var/www/farmacia/backend && php artisan schedule:run >> /dev/null 2>&1
```

El comando `php artisan qr:reconcile` consulta hasta 50 intentos por ejecución, priorizando los que llevan más tiempo sin actualizarse. No vuelve a generar QR. Sin el planificador, funcionan las consultas desde el panel y el callback SIP; BNB requiere una de las consultas para conocer el estado.

## Clientes, compras y apariencia

- Clientes: catálogo con nombre, carnet, teléfono, dirección y estado. Al salir del campo documento del POS se busca coincidencia y se completan los datos. También hay búsqueda manual por nombre o carnet y selección. Si introduces datos nuevos se guardan al confirmar la venta; sin documento se crea un registro nuevo, por lo que conviene seleccionar el existente para evitar duplicados por nombre.
- La migración recupera clientes de ventas anteriores que tienen nombre y documento, usando el nombre más reciente por documento. Los recibos históricos conservan sus textos. Se normalizan mayúsculas y espacios del documento, sin eliminar ceros iniciales ni guiones. No se unen personas solo por nombre.
- Ventas: el icono del ojo abre detalle con productos, lotes/vencimientos, pagos, cliente, descuentos y revisión de receta. La impresora abre el recibo y mantiene la marca de copia al reimprimir.
- Abonar en Compras: corregida la generación del identificador cuando randomUUID no existe en HTTP de red local. Utiliza getRandomValues y conserva el identificador al reintentar un abono.
- Apariencia: oscuro neutro con naranja, claro o según el equipo. La elección se recuerda en el navegador; Sistema reacciona al cambio del equipo. Acciones de filas con iconos, título y nombre accesible. Los botones principales conservan texto para orientar al operador.

## Validación y pendiente de puesta en marcha

Las pruebas automatizadas usan respuestas de contrato controladas; no son transacciones bancarias reales. Antes de producción falta validar autenticación, generación, consulta, anulación y callback con las credenciales de pruebas asignadas a la farmacia. No se incluyó un modo de pagos simulados en la aplicación entregada.
