Casa de Cambio — Estabilidad y hardening
Nueva función SQL apply_currency_balance_delta que aplica el delta de saldo en una sola operación atómica (UPSERT + suma), eliminando el race read-modify-write que podía generar drift cuando dos operaciones tocaban el mismo cajón/moneda al mismo tiempo. executeExchangeOperation, createCashCurrencyMovement, reverseCashCurrencyMovement y la apertura de caja con base Casa de Cambio usan ahora esta función. exchange_transactions gana columna idempotency_key con índice único parcial por owner: el cliente envía una clave por intento, y un doble-submit colapsa server-side al mismo registro en lugar de duplicarlo. Diálogo de movimientos USD/MXN con submitLockRef sincrónico anti doble-clic. Nuevos índices en cash_currency_movements (owner+register+created_at, reversal_of_id, related_exchange_id) y exchange_transactions (owner+register+created_at) para mantener el historial y el reporte de cierre rápidos a cualquier volumen.
Aspectos destacados
- Saldos de divisas actualizados atómicamente vía SQL
- Sin drift por race-condition multi-caja/multi-usuario
- Idempotency key por operación de cambio (anti doble-submit)
- Guarda síncrona anti doble-clic en diálogo de movimientos
- Reversa idempotente con rollback en race detectada (ya existente)
- Índices nuevos: movimientos por owner+caja+fecha y reversas
- Índice nuevo en exchange_transactions para historial/cierre
- Sin regresión para tenants sin el add-on