Se detectaron dos problemas en el sistema:
db671069 se cerró pero siguió marcando el tiempo9b9ca067El problema ocurría por las siguientes razones:
actualizarTemporizadores() solo verificaba !s.finalizada, sin validar otros indicadores de estadoLa función de eliminar tenía limitaciones:
// Marcar sesión como finalizada INMEDIATAMENTE en memoria
const fechaCierre = new Date().toISOString();
this.sesiones[sesionIndex].finalizada = true;
this.sesiones[sesionIndex].estado = 'finalizada';
this.sesiones[sesionIndex].fin = fechaCierre;
this.sesiones[sesionIndex].fecha_fin = fechaCierre;
Beneficio: La sesión se marca como finalizada inmediatamente, antes de cualquier operación asíncrona.
// Actualizar vista INMEDIATAMENTE (sin esperar a Supabase)
this.actualizarVista();
// Cerrar modal
const modal = bootstrap.Modal.getInstance(document.getElementById('modalFinalizarSesion'));
if (modal) {
modal.hide();
}
// Sincronizar con Supabase en segundo plano
this.recargarSesionesRemoto().catch(err => {
console.warn('⚠️ Error al recargar desde Supabase (no crítico):', err?.message || err);
});
Beneficio: La interfaz se actualiza inmediatamente, deteniendo el temporizador sin esperar confirmación de la base de datos.
actualizarTemporizadores() {
// Filtro robusto: excluir sesiones finalizadas, cerradas o con estado finalizado
const sesionesActivas = this.sesiones.filter(s => {
const esFinalizada = s.finalizada === true;
const estadoFinalizado = s.estado === 'finalizada' || s.estado === 'cerrada' || s.estado === 'cancelada';
// Sesión es activa solo si NO está finalizada en ninguna forma
const esActiva = !esFinalizada && !estadoFinalizado;
return esActiva;
});
// ...
}
Beneficio: Verifica múltiples indicadores de estado, no solo el flag finalizada.
finalizarSesion(sesionId) {
const sesion = this.sesiones.find(s => s.id === sesionId);
if (!sesion) {
console.warn('⚠️ No se encontró la sesión:', sesionId);
return;
}
// ===== PROTECCIÓN CONTRA DOBLE CIERRE =====
if (sesion.finalizada === true || sesion.estado === 'finalizada' || sesion.estado === 'cerrada') {
console.warn('⚠️ Intento de cerrar sesión ya finalizada:', sesionId);
mostrarNotificacion('Esta sesión ya fue finalizada anteriormente', 'warning');
return;
}
// ...
}
Beneficio: Evita procesar el cierre de una sesión que ya está finalizada, previniendo entradas duplicadas.
// Verificar inconsistencias: si tiene fecha_fin pero no está marcada como finalizada
if (sesion.fecha_fin && !sesion.finalizada) {
console.warn(' - ⚠️ INCONSISTENCIA: Sesión con fecha_fin pero no finalizada:', sesion.id);
console.warn(' Marcando automáticamente como finalizada...');
sesion.finalizada = true;
sesion.estado = 'finalizada';
}
Beneficio: Corrige automáticamente inconsistencias en los datos, evitando estados ambiguos.
async eliminarRegistro(sesionId) {
// Validación previa
const sesion = this.sesiones.find(s => s.id === sesionId);
if (!sesion) {
console.warn('⚠️ No se encontró la sesión:', sesionId);
mostrarNotificacion('No se encontró el registro de venta', 'warning');
return;
}
// ===== ELIMINAR DIRECTAMENTE DESDE SUPABASE =====
if (sesion.ventaId) {
// Si viene del modelo contable, anular en lugar de borrar
const resultado = await window.databaseService.update('ventas', sesion.ventaId, {
estado: 'anulada',
updated_at: new Date().toISOString()
});
} else {
// Eliminar directamente de la tabla sesiones
const resultado = await window.databaseService.delete('sesiones', sesionId);
}
// ===== RECARGAR DATOS DESDE SUPABASE =====
await this.cargarDesdeSupabase();
this.actualizarEstadisticas();
this.actualizarHistorialVentas();
mostrarNotificacion('Registro de venta eliminado correctamente', 'success');
}
Beneficio: Elimina directamente desde Supabase y recarga los datos para mantener sincronización.
catch (e) {
console.error('❌ Error al eliminar el registro:', e);
// Mensajes de error más específicos
let mensajeError = 'No se pudo eliminar el registro.';
if (e?.message?.includes('permission')) {
mensajeError = 'No tienes permisos para eliminar este registro. Contacta al administrador.';
} else if (e?.message?.includes('not found')) {
mensajeError = 'El registro ya no existe en la base de datos.';
}
mostrarNotificacion(mensajeError, 'danger');
}
Beneficio: Mensajes de error claros y específicos según el tipo de problema.
console.log('🗑️ Intentando eliminar registro:', sesionId);
console.log(' - Sesión a eliminar:', sesion);
console.log('🔄 Eliminando desde Supabase...');
console.log('✅ Sesión eliminada correctamente de Supabase');
console.log('🔄 Recargando datos desde Supabase...');
Beneficio: Facilita la depuración y seguimiento de operaciones.
✅ Las sesiones se marcan como finalizadas inmediatamente en la interfaz ✅ Los temporizadores dejan de actualizarse instantáneamente al cerrar ✅ No se pueden cerrar sesiones ya finalizadas (protección contra doble cierre) ✅ Se detectan y corrigen automáticamente inconsistencias de estado ✅ Mejor logging para depuración de problemas futuros
✅ Los registros se eliminan directamente desde Supabase ✅ Los datos se recargan después de eliminar para mantener sincronización ✅ Mensajes de error específicos según el tipo de problema ✅ Logging detallado para seguimiento de operaciones ✅ Validación previa antes de intentar eliminar
✅ Sesión marcada como finalizada en memoria: {id: "...", finalizada: true, estado: "finalizada"}
⚠️ Intento de cerrar sesión ya finalizada: ...
🗑️ Intentando eliminar registro: ...
🔄 Eliminando desde Supabase...
✅ Sesión eliminada correctamente de Supabase
🔄 Recargando datos desde Supabase...
Correcciones de cierre de sesiones:
Correcciones de eliminación:
eliminarRegistro() mejorada
Fecha de corrección: 25 de enero de 2026 Archivos modificados: