diff --git a/app/controllers/configuracion.php b/app/controllers/configuracion.php index cc8e231..08d7928 100644 --- a/app/controllers/configuracion.php +++ b/app/controllers/configuracion.php @@ -97,9 +97,4 @@ function guardar() function automatizaciones() { include __DIR__ . '/../../views/configuracion/automatizaciones.php'; -} - -function preferencias() -{ - include __DIR__ . '/../../views/configuracion/preferencias.php'; } \ No newline at end of file diff --git a/app/controllers/preferencias.php b/app/controllers/preferencias.php new file mode 100644 index 0000000..b065464 --- /dev/null +++ b/app/controllers/preferencias.php @@ -0,0 +1,342 @@ + 0, 'notificaciones_extra' => 0]; + sqlsrv_free_stmt($stmt); + + // Obtener preferencias específicas de notificaciones + $query = "SELECT * FROM preferencias_notificaciones_usuario WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]); + if ($stmt && sqlsrv_execute($stmt)) { + $preferenciasRow = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); + sqlsrv_free_stmt($stmt); + } else { + $preferenciasRow = false; + } + + // Si no existe registro, crear valores por defecto + if (!$preferenciasRow) { + $preferencias = [ + 'nuevas_solicitudes' => 0, + 'registro_solicitud' => 0, + 'cambio_estado' => 0, + 'resumen_diario' => 0, + 'alertas_tiempo' => 0, + 'documentos_expediente' => 0, + 'nuevos_archivos' => 0, + 'intentos_fallidos' => 0, + 'bloqueo_cuenta' => 0 + ]; + } else { + $preferencias = $preferenciasRow; + } + + // Obtener tipos de notificaciones disponibles + $query = "SELECT nombre, descripcion FROM tipos_notificaciones ORDER BY nombre"; + $stmt = sqlsrv_query($conn, $query); + if (!$stmt) { + die("Error al obtener tipos: " . print_r(sqlsrv_errors(), true)); + } + + // Crear array asociativo para la vista + $tipos = []; + while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { + $tipos[$row['nombre']] = $row['descripcion']; + } + sqlsrv_free_stmt($stmt); + + // Obtener correo extra si existe + $query = "SELECT correo FROM correo_extra WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$idUsuario]); + $correoExtra = ''; + if ($stmt && sqlsrv_execute($stmt)) { + $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); + $correoExtra = $row ? $row['correo'] : ''; + sqlsrv_free_stmt($stmt); + } + + sqlsrv_close($conn); + include __DIR__ . '/../../views/preferencias/notificaciones.php'; +} + +function guardarPreferenciasAjax() +{ + // Verificar que sea una petición AJAX + if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest') { + http_response_code(400); + echo json_encode(['success' => false, 'message' => 'Petición inválida']); + exit; + } + + // Verificar método POST + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + http_response_code(405); + echo json_encode(['success' => false, 'message' => 'Método no permitido']); + exit; + } + + $conn = getConnection(); + + // Verificar autenticación + if (!isset($_SESSION['usuario_id']) || ($_SESSION['pendiente_confirmacion'] ?? false)) { + http_response_code(401); + echo json_encode(['success' => false, 'message' => 'Usuario no autenticado']); + exit; + } + + $id_usuario = $_SESSION['usuario_id']; + + try { + // Leer datos JSON del cuerpo de la petición + $input = json_decode(file_get_contents('php://input'), true); + + if (!$input) { + throw new Exception("Datos inválidos"); + } + + // Iniciar transacción + sqlsrv_begin_transaction($conn); + + // Determinar qué tipo de cambio se está realizando + $tipo_cambio = $input['tipo'] ?? 'general'; + + switch ($tipo_cambio) { + case 'notificaciones_general': + $notificaciones = $input['valor'] ? 1 : 0; + + // Si se desactivan las notificaciones, también desactivar notificaciones extra + $notificaciones_extra = $notificaciones ? ($input['notificaciones_extra'] ?? 0) : 0; + + $query = "UPDATE usuarios_sistema SET notificaciones = ?, notificaciones_extra = ? WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$notificaciones, $notificaciones_extra, $id_usuario]); + + if (!$stmt || !sqlsrv_execute($stmt)) { + throw new Exception("Error al actualizar configuración general"); + } + sqlsrv_free_stmt($stmt); + + // Si se desactivan las notificaciones, limpiar preferencias específicas + if (!$notificaciones) { + $query_delete = "DELETE FROM preferencias_notificaciones_usuario WHERE id_usuario = ?"; + $stmt_delete = sqlsrv_prepare($conn, $query_delete, [$id_usuario]); + if ($stmt_delete) { + sqlsrv_execute($stmt_delete); + sqlsrv_free_stmt($stmt_delete); + } + } + break; + + case 'notificaciones_extra': + $notificaciones_extra = $input['valor'] ? 1 : 0; + + // Validar que existe correo extra si se quiere activar + if ($notificaciones_extra) { + $query_check = "SELECT correo FROM correo_extra WHERE id_usuario = ?"; + $stmt_check = sqlsrv_prepare($conn, $query_check, [$id_usuario]); + if ($stmt_check && sqlsrv_execute($stmt_check)) { + $row = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); + sqlsrv_free_stmt($stmt_check); + + if (!$row || empty($row['correo'])) { + throw new Exception("No tienes un correo adicional registrado. Ve a Seguridad para registrar uno primero."); + } + } else { + throw new Exception("No tienes un correo adicional registrado. Ve a Seguridad para registrar uno primero."); + } + } + + $query = "UPDATE usuarios_sistema SET notificaciones_extra = ? WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$notificaciones_extra, $id_usuario]); + + if (!$stmt || !sqlsrv_execute($stmt)) { + throw new Exception("Error al actualizar configuración de correo extra"); + } + sqlsrv_free_stmt($stmt); + break; + + case 'tipo_notificacion': + $tipo_nombre = $input['nombre'] ?? ''; + $valor = $input['valor'] ? 1 : 0; + + if (empty($tipo_nombre)) { + throw new Exception("Tipo de notificación no especificado"); + } + + // Verificar que las notificaciones generales estén activadas + $query_check = "SELECT notificaciones FROM usuarios_sistema WHERE id_usuario = ?"; + $stmt_check = sqlsrv_prepare($conn, $query_check, [$id_usuario]); + if ($stmt_check && sqlsrv_execute($stmt_check)) { + $row = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); + sqlsrv_free_stmt($stmt_check); + + if (!$row || !$row['notificaciones']) { + throw new Exception("Las notificaciones generales deben estar activadas primero"); + } + } else { + throw new Exception("Error al verificar configuración"); + } + + // Verificar si existe el registro + $query_exists = "SELECT COUNT(*) as count FROM preferencias_notificaciones_usuario WHERE id_usuario = ?"; + $stmt_exists = sqlsrv_prepare($conn, $query_exists, [$id_usuario]); + $exists = false; + if ($stmt_exists && sqlsrv_execute($stmt_exists)) { + $row = sqlsrv_fetch_array($stmt_exists, SQLSRV_FETCH_ASSOC); + $exists = $row['count'] > 0; + sqlsrv_free_stmt($stmt_exists); + } + + if ($exists) { + // Actualizar el campo específico + $query = "UPDATE preferencias_notificaciones_usuario SET $tipo_nombre = ? WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$valor, $id_usuario]); + } else { + // Crear registro con valores por defecto y el campo específico + $tipos_default = [ + 'nuevas_solicitudes' => 0, + 'registro_solicitud' => 0, + 'cambio_estado' => 0, + 'resumen_diario' => 0, + 'alertas_tiempo' => 0, + 'documentos_expediente' => 0, + 'nuevos_archivos' => 0, + 'intentos_fallidos' => 0, + 'bloqueo_cuenta' => 0 + ]; + + // Establecer el valor específico + $tipos_default[$tipo_nombre] = $valor; + + $campos = implode(', ', array_keys($tipos_default)); + $placeholders = rtrim(str_repeat('?, ', count($tipos_default)), ', '); + $query = "INSERT INTO preferencias_notificaciones_usuario (id_usuario, $campos) VALUES (?, $placeholders)"; + + $params = array_merge([$id_usuario], array_values($tipos_default)); + $stmt = sqlsrv_prepare($conn, $query, $params); + } + + if (!$stmt || !sqlsrv_execute($stmt)) { + throw new Exception("Error al actualizar preferencia específica"); + } + sqlsrv_free_stmt($stmt); + break; + + default: + throw new Exception("Tipo de cambio no válido"); + } + + sqlsrv_commit($conn); + sqlsrv_close($conn); + + echo json_encode([ + 'success' => true, + 'message' => 'Preferencias guardadas automáticamente', + 'tipo' => $tipo_cambio + ]); + + } catch (Exception $e) { + sqlsrv_rollback($conn); + sqlsrv_close($conn); + + http_response_code(400); + echo json_encode([ + 'success' => false, + 'message' => $e->getMessage(), + 'tipo' => $tipo_cambio ?? 'unknown' + ]); + } + exit; +} + +// Función auxiliar para obtener el correo extra de un usuario (útil para el sistema de notificaciones) +function obtenerCorreoExtra($id_usuario) +{ + $conn = getConnection(); + $query = " + SELECT ce.correo + FROM correo_extra ce + INNER JOIN usuarios_sistema us ON ce.id_usuario = us.id_usuario + WHERE ce.id_usuario = ? AND us.notificaciones_extra = 1 + "; + $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); + $correo = null; + if ($stmt && sqlsrv_execute($stmt)) { + $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); + $correo = $row ? $row['correo'] : null; + sqlsrv_free_stmt($stmt); + } + sqlsrv_close($conn); + return $correo; +} + +// Función auxiliar para obtener todas las preferencias de notificación de un usuario +function obtenerPreferenciasNotificacion($id_usuario) +{ + $conn = getConnection(); + + // Obtener configuración general + $query = "SELECT notificaciones, notificaciones_extra FROM usuarios_sistema WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); + if (!$stmt || !sqlsrv_execute($stmt)) { + sqlsrv_close($conn); + return null; + } + $config = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); + sqlsrv_free_stmt($stmt); + + if (!$config || !$config['notificaciones']) { + sqlsrv_close($conn); + return null; // Usuario no tiene notificaciones activadas + } + + // Obtener preferencias específicas + $query = "SELECT * FROM preferencias_notificaciones_usuario WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); + $preferencias = null; + if ($stmt && sqlsrv_execute($stmt)) { + $preferencias = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); + sqlsrv_free_stmt($stmt); + } + + // Obtener correo extra si está activado + $correo_extra = null; + if ($config['notificaciones_extra']) { + $query = "SELECT correo FROM correo_extra WHERE id_usuario = ?"; + $stmt = sqlsrv_prepare($conn, $query, [$id_usuario]); + if ($stmt && sqlsrv_execute($stmt)) { + $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); + $correo_extra = $row ? $row['correo'] : null; + sqlsrv_free_stmt($stmt); + } + } + + sqlsrv_close($conn); + return [ + 'config_general' => $config, + 'preferencias' => $preferencias, + 'correo_extra' => $correo_extra + ]; +} \ No newline at end of file diff --git a/notificaciones_table.txt b/notificaciones_table.txt new file mode 100644 index 0000000..8f808f7 --- /dev/null +++ b/notificaciones_table.txt @@ -0,0 +1,34 @@ +ALTER TABLE usuarios_sistema +ADD notificaciones BIT DEFAULT 0, + notificaciones_extra BIT DEFAULT 0; + +CREATE TABLE tipos_notificaciones ( + id INT PRIMARY KEY IDENTITY, + nombre NVARCHAR(255) NOT NULL, + descripcion NVARCHAR(500) NULL +); + +INSERT INTO tipos_notificaciones (nombre, descripcion) VALUES +('nuevas_solicitudes', 'Creación de nuevas solicitudes de importación'), +('registro_solicitud', 'Notificación inmediata al registrar una solicitud'), +('cambio_estado', 'Cambio de estado de solicitudes de importación'), +('resumen_diario', 'Resumen diario de solicitudes de importación'), +('alertas_tiempo', 'Alertas por tiempo excedido en estados críticos'), +('documentos_expediente', 'Incorporación de documentos al expediente electrónico'), +('nuevos_archivos', 'Aviso al agregarse nuevos archivos o documentos'), +('intentos_fallidos', 'Intentos fallidos de acceso'), +('bloqueo_cuenta', 'Bloqueo de cuenta'); + +CREATE TABLE preferencias_notificaciones_usuario ( + id_usuario INT PRIMARY KEY, + nuevas_solicitudes BIT DEFAULT 0, + registro_solicitud BIT DEFAULT 0, + cambio_estado BIT DEFAULT 0, + resumen_diario BIT DEFAULT 0, + alertas_tiempo BIT DEFAULT 0, + documentos_expediente BIT DEFAULT 0, + nuevos_archivos BIT DEFAULT 0, + intentos_fallidos BIT DEFAULT 0, + bloqueo_cuenta BIT DEFAULT 0, + FOREIGN KEY (id_usuario) REFERENCES usuarios_sistema(id_usuario) +); diff --git a/views/partials/sidebar_configuracion.php b/views/partials/sidebar_configuracion.php index 7a65b24..08bbe1a 100644 --- a/views/partials/sidebar_configuracion.php +++ b/views/partials/sidebar_configuracion.php @@ -63,6 +63,8 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador $esVistaBitacoras = str_contains($_SERVER['REQUEST_URI'], '/bitacoras'); // Detecta si estamos en alguna parta de seguridad $esVistaSeguridad = str_contains($_SERVER['REQUEST_URI'], '/seguridad'); + // Detecta si estamos en alguna parte de preferencias + $esVistaPreferencias = str_contains($_SERVER['REQUEST_URI'], '/preferencias') ?> @@ -78,10 +80,31 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador - - ✅ Preferencias - + + + + role="button" aria-expanded="true" aria-controls="submenuPreferencias" + onclick=""> + ✅ Preferencias + 1 + + + + + ✅ Preferencias + 1 + + @@ -102,7 +125,7 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador - + 👮 Seguridad @@ -130,7 +153,7 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador - + @@ -159,10 +182,31 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador - - ✅ Preferencias - + + + + role="button" aria-expanded="true" aria-controls="submenuPreferencias" + onclick=""> + ✅ Preferencias + 1 + + + + + ✅ Preferencias + 1 + + @@ -183,7 +227,7 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador - + 👮 Seguridad @@ -211,7 +255,7 @@ if (!isset($_SESSION['usuario_id']) || $_SESSION['tipo_usuario'] !== 'importador - + diff --git a/views/configuracion/preferencias.php b/views/preferencias/dashboard_preferencias.php similarity index 79% rename from views/configuracion/preferencias.php rename to views/preferencias/dashboard_preferencias.php index 44977e6..6a52a3b 100644 --- a/views/configuracion/preferencias.php +++ b/views/preferencias/dashboard_preferencias.php @@ -78,9 +78,23 @@ include __DIR__ . '/../partials/sidebar_configuracion.php'; -
+

✅ Preferencias

+
+
\ No newline at end of file diff --git a/views/preferencias/notificaciones.php b/views/preferencias/notificaciones.php new file mode 100644 index 0000000..ae42a78 --- /dev/null +++ b/views/preferencias/notificaciones.php @@ -0,0 +1,471 @@ + + + + + + Dashboard | Configuración + + + + + + + +
+
+

🔔 Gestión de Notificaciones

+
+ + + +
+ ✅ Las preferencias de notificación se han guardado correctamente. +
+ + + +
+ ❌ Error: +
+ + +
+ +
+
+ > + +
Activa o desactiva todas las notificaciones del sistema
+
+
+ + +
> + +
+
📋 Tipos de Notificaciones
+
+ $descripcion): ?> +
+
+ > + +
+
+ +
+
+
+ + +
+
+ > + +
Recibe una copia de las notificaciones en un correo adicional
+
+ + +
> + + +
+
+ +
+
+ 📧 Correo adicional configurado:
+ +
+ Las notificaciones se enviarán también a este correo. + + Gestionar en Seguridad → + +
+
+
+ +
+
+ +
+
+ ⚠️ No hay correo adicional registrado
+
+ Para usar esta función, primero debes registrar un correo adicional en la sección de Seguridad. + + Ir a Seguridad → + +
+
+
+ +
+
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/views/seguridad/dashboard_seguridad.php b/views/seguridad/dashboard_seguridad.php index 84c76b8..e8a9f8f 100644 --- a/views/seguridad/dashboard_seguridad.php +++ b/views/seguridad/dashboard_seguridad.php @@ -84,20 +84,20 @@ include __DIR__ . '/../partials/sidebar_configuracion.php';
-
-

Autenticación de dos factores

-
-
- > - -
-
+
+

Autenticación de dos factores

+
+
+ > + +
+
+
-