isSMTP(); $mail->Host = 'secure.emailsrvr.com'; $mail->SMTPAuth = true; $mail->Username = 'noreply@aduanasoft.com.mx'; $mail->Password = $_ENV['SMTP_PASS']; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587; $mail->setFrom('noreply@aduanasoft.com.mx', 'SIIH | AduanaSoft'); $mail->addAddress($email); $mail->CharSet = 'UTF-8'; $mail->isHTML(true); $mail->Subject = 'Tu acceso a la plataforma SIIH ha sido autorizado'; $mail->Body = "

¡Bienvenido a SIIH!

Tu registro como importador ha sido aprobado. Aquí tienes tus credenciales de acceso:

Correo: $email

Contraseña: $password_plain

📌 Te recomendamos cambiar tu contraseña una vez que ingreses al sistema.

Ir al sistema

© " . date('Y') . " SIIH · Desarrollado por AduanaSoft
"; $mail->send(); } catch (Exception $e) { error_log("Error al enviar correo: {$mail->ErrorInfo}"); } header("Location: /IMPORTADORES/AGENTES/solicitudes_pendientes"); exit; } function activos() { if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } require_once __DIR__ . '/../helpers/crypto.php'; $conn = getConnection(); $sql = "SELECT id_usuario, nombre, email, tipo_usuario, creado_en, activo FROM usuarios_sistema WHERE tipo_usuario = 'importador' ORDER BY creado_en DESC"; $stmt = sqlsrv_query($conn, $sql); $importadores = []; if ($stmt) { while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $row['nombre'] = decrypt($row['nombre']); $row['email'] = decrypt($row['email']); $importadores[] = $row; } } include __DIR__ . '/../../views/agentes/importadores_activos.php'; } function toggle_estado() { if (!($_SESSION['usuario_id'] ?? false) || $_SESSION['tipo_usuario'] !== 'agente_aduanal') { die("⚠️ No autorizado."); } $id = $_GET['id'] ?? null; if (!$id || !is_numeric($id)) { die("❌ ID inválido."); } $conn = getConnection(); $sql = "SELECT activo FROM usuarios_sistema WHERE id_usuario = ?"; $stmt = sqlsrv_query($conn, $sql, [$id]); if (!$stmt || !($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC))) { die("❌ Usuario no encontrado."); } $nuevoEstado = $row['activo'] == 1 ? 0 : 1; $update = "UPDATE usuarios_sistema SET activo = ? WHERE id_usuario = ?"; $result = sqlsrv_query($conn, $update, [$nuevoEstado, $id]); if (!$result) { die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true)); } // Guardar en bitácora require_once __DIR__ . '/../helpers/bitacoras.php'; registrar_bitacora_usuario($_SESSION['usuario_id'], 'toggle_estado', "Modificó estado del usuario $id a $nuevoEstado"); header("Location: /IMPORTADORES/agentes/activos"); exit; } function bitacora() { $conn = getConnection(); if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; } $sql = " SELECT u.id_usuario, u.nombre, b.email, b.ip, b.fecha, b.exito, b.detalle FROM dbo.bitacora_login b JOIN dbo.usuarios_sistema u ON u.id_usuario = b.id_usuario ORDER BY b.fecha DESC "; $stmt = sqlsrv_query($conn, $sql); if ($stmt === false) { die("Error en bitacora(): " . print_r(sqlsrv_errors(), true)); } $bitacoras = []; while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $row['nombre'] = decrypt($row['nombre']); // Desencripta aquí $bitacoras[] = $row; } include __DIR__ . '/../../views/agentes/bitacora.php'; } function lista() { $conn = getConnection(); $locaciones = []; // CONSULTA CORREGIDA - Agregamos abreviatura e iso2 $sql = " SELECT p.id_pais, p.nombre AS nombre_pais, p.iso2, p.iso3, e.id_estado, e.nombre AS nombre_estado, e.abreviatura, c.id_ciudad, c.nombre AS nombre_ciudad FROM paises p LEFT JOIN estados e ON p.id_pais = e.pais_id LEFT JOIN ciudades c ON e.id_estado = c.estado_id ORDER BY p.id_pais, e.id_estado, c.id_ciudad "; $stmt = sqlsrv_query($conn, $sql); if (!$stmt) { $errors = sqlsrv_errors(); error_log("Error en consulta lista(): " . print_r($errors, true)); die("Error en la consulta"); } while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $locaciones[] = $row; } // Obtener países para los selects del modal $sql_paises_select = "SELECT id_pais, nombre FROM paises ORDER BY nombre"; $stmt_paises_select = sqlsrv_query($conn, $sql_paises_select); $paises = []; while ($row = sqlsrv_fetch_array($stmt_paises_select, SQLSRV_FETCH_ASSOC)) { $paises[] = $row; } include __DIR__ . '/../../views/locaciones/gestion_locaciones.php'; } function alta() { $conn = getConnection(); // 1) Cargar países $sql = "SELECT id_pais, nombre FROM paises ORDER BY nombre"; $stmt = sqlsrv_query($conn, $sql); $paises = []; while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $paises[] = $row; } include __DIR__ . '/../../views/locaciones/alta_locaciones.php'; } // AJAX: devuelve los estados de un país dado function estados() { header('Content-Type: application/json; charset=utf-8'); $pais = $_GET['pais'] ?? ''; $conn = getConnection(); $sql = "SELECT id_estado, nombre FROM estados WHERE pais_id = ? ORDER BY nombre"; $stmt = sqlsrv_query($conn, $sql, [$pais]); $out = []; while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $out[] = $r; } echo json_encode($out); exit; } // Guardar nuevo estado function guardarEstado() { header('Content-Type: application/json; charset=utf-8'); try { // Debug: Verificar qué se está recibiendo error_log("POST data: " . print_r($_POST, true)); $pais_id = $_POST['pais'] ?? ''; $entidad = trim($_POST['entidad'] ?? ''); // Debug: Verificar valores específicos error_log("pais_id: '$pais_id', entidad: '$entidad'"); // Validaciones más específicas if (empty($pais_id)) { echo json_encode(['success' => false, 'message' => 'Debe seleccionar un país']); exit; } if (empty($entidad)) { echo json_encode(['success' => false, 'message' => 'Debe ingresar el nombre del estado']); exit; } $conn = getConnection(); // Verificar que el país existe $sql_pais = "SELECT COUNT(*) as count FROM paises WHERE id_pais = ?"; $stmt_pais = sqlsrv_query($conn, $sql_pais, [$pais_id]); $pais_exists = sqlsrv_fetch_array($stmt_pais, SQLSRV_FETCH_ASSOC); if ($pais_exists['count'] == 0) { echo json_encode(['success' => false, 'message' => 'El país seleccionado no existe']); exit; } // Verificar si ya existe el estado en ese país $sql_check = "SELECT COUNT(*) as count FROM estados WHERE pais_id = ? AND nombre = ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$pais_id, $entidad]); $exists = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($exists['count'] > 0) { echo json_encode(['success' => false, 'message' => 'Este estado ya existe en el país seleccionado']); exit; } // Insertar nuevo estado // Primero obtenemos el siguiente ID disponible $sql_max = "SELECT ISNULL(MAX(id_estado), 0) + 1 as next_id FROM estados"; $stmt_max = sqlsrv_query($conn, $sql_max); $next_id_row = sqlsrv_fetch_array($stmt_max, SQLSRV_FETCH_ASSOC); $next_id = $next_id_row['next_id']; $sql = "INSERT INTO estados (id_estado, pais_id, nombre) VALUES (?, ?, ?)"; $stmt = sqlsrv_query($conn, $sql, [$next_id, $pais_id, $entidad]); if ($stmt) { echo json_encode(['success' => true, 'message' => 'Estado registrado exitosamente']); } else { // Obtener el error específico de SQL Server $errors = sqlsrv_errors(); $errorMessage = 'Error al registrar el estado'; if ($errors) { $errorMessage .= ': ' . $errors[0]['message']; } error_log("Error SQL: " . print_r($errors, true)); echo json_encode(['success' => false, 'message' => $errorMessage]); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; } // Guardar nueva ciudad function guardarCiudad() { header('Content-Type: application/json; charset=utf-8'); try { $estado_id = $_POST['entidad'] ?? ''; $ciudad = trim($_POST['ciudad'] ?? ''); // Validaciones if (empty($estado_id) || empty($ciudad)) { echo json_encode(['success' => false, 'message' => 'Todos los campos son obligatorios']); exit; } $conn = getConnection(); // Verificar si ya existe la ciudad en ese estado $sql_check = "SELECT COUNT(*) as count FROM ciudades WHERE estado_id = ? AND nombre = ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$estado_id, $ciudad]); $exists = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($exists['count'] > 0) { echo json_encode(['success' => false, 'message' => 'Esta ciudad ya existe en el estado seleccionado']); exit; } // Insertar nueva ciudad $sql = "INSERT INTO ciudades (estado_id, nombre) VALUES (?, ?)"; $stmt = sqlsrv_query($conn, $sql, [$estado_id, $ciudad]); if ($stmt) { echo json_encode(['success' => true, 'message' => 'Ciudad registrada exitosamente']); } else { echo json_encode(['success' => false, 'message' => 'Error al registrar la ciudad']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; } // Función para obtener país por estado (necesaria para el modal de edición de ciudades) function obtenerPaisPorEstado() { header('Content-Type: application/json; charset=utf-8'); try { $estado_id = $_GET['estado'] ?? ''; if (empty($estado_id)) { echo json_encode(['success' => false, 'message' => 'ID de estado requerido']); exit; } $conn = getConnection(); $sql = "SELECT pais_id FROM estados WHERE id_estado = ?"; $stmt = sqlsrv_query($conn, $sql, [$estado_id]); if ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { echo json_encode(['success' => true, 'pais_id' => $row['pais_id']]); } else { echo json_encode(['success' => false, 'message' => 'Estado no encontrado']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; } // FUNCIÓN DISPATCHER PARA EDICIÓN function editar() { $tipo = $_POST['tipo'] ?? ''; // Log para debugging error_log("Función editar llamada con tipo: " . $tipo); error_log("POST data: " . print_r($_POST, true)); switch ($tipo) { case 'pais': actualizarPais(); break; case 'estado': actualizarEstado(); break; case 'ciudad': actualizarCiudad(); break; default: header('Content-Type: application/json; charset=utf-8'); echo json_encode(['success' => false, 'message' => 'Tipo de elemento no válido: ' . $tipo]); exit; } } // FUNCIÓN ESPECÍFICA PARA ACTUALIZAR PAÍSES function actualizarPais() { header('Content-Type: application/json; charset=utf-8'); try { $id = $_POST['id'] ?? ''; $nombre = trim($_POST['nombre'] ?? ''); $iso2 = trim($_POST['iso2'] ?? ''); $iso3 = trim($_POST['iso3'] ?? ''); // Validaciones if (empty($id) || empty($nombre)) { echo json_encode(['success' => false, 'message' => 'ID y nombre del país son obligatorios']); exit; } $conn = getConnection(); if (!$conn) { echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); exit; } // Verificar duplicados $sql_check = "SELECT COUNT(*) as count FROM paises WHERE nombre = ? AND id_pais != ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$nombre, $id]); if (!$stmt_check) { echo json_encode(['success' => false, 'message' => 'Error al verificar duplicados']); exit; } $exists = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($exists['count'] > 0) { echo json_encode(['success' => false, 'message' => 'Ya existe otro país con este nombre']); exit; } // Actualizar $iso2_val = empty($iso2) ? null : $iso2; $iso3_val = empty($iso3) ? null : $iso3; $sql = "UPDATE paises SET nombre = ?, iso2 = ?, iso3 = ? WHERE id_pais = ?"; $params = [$nombre, $iso2_val, $iso3_val, $id]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt && sqlsrv_rows_affected($stmt) > 0) { echo json_encode(['success' => true, 'message' => 'País actualizado exitosamente']); } else { echo json_encode(['success' => false, 'message' => 'No se pudo actualizar el país']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; } // FUNCIÓN ESPECÍFICA PARA ACTUALIZAR ESTADOS function actualizarEstado() { header('Content-Type: application/json; charset=utf-8'); try { $id = $_POST['id'] ?? ''; $nombre = trim($_POST['nombre'] ?? ''); $abreviatura = trim($_POST['abreviatura'] ?? ''); $pais_id = $_POST['pais_id'] ?? ''; // Validaciones if (empty($id) || empty($nombre) || empty($pais_id)) { echo json_encode(['success' => false, 'message' => 'ID, nombre del estado y país son obligatorios']); exit; } $conn = getConnection(); if (!$conn) { echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); exit; } // Verificar duplicados $sql_check = "SELECT COUNT(*) as count FROM estados WHERE nombre = ? AND pais_id = ? AND id_estado != ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$nombre, $pais_id, $id]); if (!$stmt_check) { echo json_encode(['success' => false, 'message' => 'Error al verificar duplicados']); exit; } $exists = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($exists['count'] > 0) { echo json_encode(['success' => false, 'message' => 'Ya existe otro estado con este nombre en el país seleccionado']); exit; } // Actualizar $abreviatura_val = empty($abreviatura) ? null : $abreviatura; $sql = "UPDATE estados SET nombre = ?, abreviatura = ?, pais_id = ? WHERE id_estado = ?"; $params = [$nombre, $abreviatura_val, $pais_id, $id]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt && sqlsrv_rows_affected($stmt) > 0) { echo json_encode(['success' => true, 'message' => 'Estado actualizado exitosamente']); } else { echo json_encode(['success' => false, 'message' => 'No se pudo actualizar el estado']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; } // FUNCIÓN ESPECÍFICA PARA ACTUALIZAR CIUDADES function actualizarCiudad() { header('Content-Type: application/json; charset=utf-8'); try { $id = $_POST['id'] ?? ''; $nombre = trim($_POST['nombre'] ?? ''); $estado_id = $_POST['estado_id'] ?? ''; // Validaciones if (empty($id) || empty($nombre) || empty($estado_id)) { echo json_encode(['success' => false, 'message' => 'ID, nombre de la ciudad y estado son obligatorios']); exit; } $conn = getConnection(); if (!$conn) { echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); exit; } // Verificar duplicados $sql_check = "SELECT COUNT(*) as count FROM ciudades WHERE nombre = ? AND estado_id = ? AND id_ciudad != ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$nombre, $estado_id, $id]); if (!$stmt_check) { echo json_encode(['success' => false, 'message' => 'Error al verificar duplicados']); exit; } $exists = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($exists['count'] > 0) { echo json_encode(['success' => false, 'message' => 'Ya existe otra ciudad con este nombre en el estado seleccionado']); exit; } // Actualizar $sql = "UPDATE ciudades SET nombre = ?, estado_id = ? WHERE id_ciudad = ?"; $params = [$nombre, $estado_id, $id]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt && sqlsrv_rows_affected($stmt) > 0) { echo json_encode(['success' => true, 'message' => 'Ciudad actualizada exitosamente']); } else { echo json_encode(['success' => false, 'message' => 'No se pudo actualizar la ciudad']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; } // Función para eliminar locaciones (países, estados, ciudades) function eliminar() { header('Content-Type: application/json; charset=utf-8'); try { // Obtener datos del JSON enviado $input = json_decode(file_get_contents('php://input'), true); $tipo = $input['tipo'] ?? ''; $id = $input['id'] ?? ''; if (empty($tipo) || empty($id)) { echo json_encode(['success' => false, 'message' => 'Datos incompletos']); exit; } $conn = getConnection(); switch ($tipo) { case 'pais': // Verificar si el país tiene estados asociados $sql_check = "SELECT COUNT(*) as count FROM estados WHERE pais_id = ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$id]); $has_estados = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($has_estados['count'] > 0) { echo json_encode(['success' => false, 'message' => 'No se puede eliminar el país porque tiene estados asociados']); exit; } // Eliminar país $sql = "DELETE FROM paises WHERE id_pais = ?"; $stmt = sqlsrv_query($conn, $sql, [$id]); if ($stmt) { echo json_encode(['success' => true, 'message' => 'País eliminado exitosamente']); } else { $errors = sqlsrv_errors(); $errorMessage = 'Error al eliminar el país'; if ($errors) { $errorMessage .= ': ' . $errors[0]['message']; } echo json_encode(['success' => false, 'message' => $errorMessage]); } break; case 'estado': // Verificar si el estado tiene ciudades asociadas $sql_check = "SELECT COUNT(*) as count FROM ciudades WHERE estado_id = ?"; $stmt_check = sqlsrv_query($conn, $sql_check, [$id]); $has_ciudades = sqlsrv_fetch_array($stmt_check, SQLSRV_FETCH_ASSOC); if ($has_ciudades['count'] > 0) { echo json_encode(['success' => false, 'message' => 'No se puede eliminar el estado porque tiene ciudades asociadas']); exit; } // Eliminar estado $sql = "DELETE FROM estados WHERE id_estado = ?"; $stmt = sqlsrv_query($conn, $sql, [$id]); if ($stmt) { echo json_encode(['success' => true, 'message' => 'Estado eliminado exitosamente']); } else { $errors = sqlsrv_errors(); $errorMessage = 'Error al eliminar el estado'; if ($errors) { $errorMessage .= ': ' . $errors[0]['message']; } echo json_encode(['success' => false, 'message' => $errorMessage]); } break; case 'ciudad': // Verificar si la ciudad está siendo utilizada en alguna relación // (aquí puedes agregar más verificaciones según tu modelo de datos) // Eliminar ciudad $sql = "DELETE FROM ciudades WHERE id_ciudad = ?"; $stmt = sqlsrv_query($conn, $sql, [$id]); if ($stmt) { echo json_encode(['success' => true, 'message' => 'Ciudad eliminada exitosamente']); } else { $errors = sqlsrv_errors(); $errorMessage = 'Error al eliminar la ciudad'; if ($errors) { $errorMessage .= ': ' . $errors[0]['message']; } echo json_encode(['success' => false, 'message' => $errorMessage]); } break; default: echo json_encode(['success' => false, 'message' => 'Tipo de elemento no válido']); break; } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => 'Error: ' . $e->getMessage()]); } exit; }