$_POST['tipo_moneda'] ?? '', 'incoterm' => $_POST['incoterm'] ?? '', 'vinculacion' => $_POST['vinculacion'] ?? '', 'pais_proveedor' => $_POST['pais_proveedor'] ?? '', 'pais_proveedor_texto' => $_POST['pais_proveedor_texto'] ?? '', 'anexo22_apendice' => $_POST['anexo22_apendice'] ?? '', 'patente' => $_POST['patente'] ?? '', 'transportista_id' => $_POST['transportista_id'] ?? '', 'chofer_id' => $_POST['chofer_id'] ?? '', 'tasa_preferencial' => $_POST['tasa_preferencial'] ?? '', 'unidad_comercial_id' => $_POST['unidad_comercial_id'] ?? '' ]; $config_json = json_encode($config, JSON_UNESCAPED_UNICODE); // Validaciones if (empty($nombre)) { die("❌ El nombre del template es obligatorio."); } if (strlen($nombre) > 100) { die("❌ El nombre del template es muy largo (máximo 100 caracteres)."); } $sql = "INSERT INTO dbo.templates_rapidos (nombre, descripcion, icono, config_json, tipo_moneda, incoterm, vinculacion, pais_proveedor, tasa_preferencial, id_agencia, id_usuario_creador) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; $params = [ $nombre, $descripcion, $icono, $config_json, $config['tipo_moneda'], $config['incoterm'], $config['vinculacion'] ?: null, $config['pais_proveedor'], $config['tasa_preferencial'], $id_agencia, $id_usuario ]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { die("❌ Error al guardar template: " . print_r(sqlsrv_errors(), true)); } header('Location: /IMPORTADORES/templates_rapidos/lista?created=ok'); exit; } function editar() { if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; } $id = $_GET['id'] ?? null; if (!$id || !is_numeric($id)) { die("❌ ID inválido."); } $conn = getConnection(); $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; // Obtener el template $sql = "SELECT * FROM dbo.templates_rapidos WHERE id = ? AND (id_usuario_creador = ? OR id_agencia = ? OR id_agencia IS NULL)"; $stmt = sqlsrv_query($conn, $sql, [$id, $id_usuario, $id_agencia]); if ($stmt === false) { die("❌ Error en consulta: " . print_r(sqlsrv_errors(), true)); } $template = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); if (!$template) { die("❌ Template no encontrado o sin permisos."); } // Decodificar configuración JSON $template['config'] = json_decode($template['config_json'], true) ?: []; // Obtener datos para los selects $conn = getConnection(); $aduanas = obtenerAduanas($conn); $patentes = obtenerPatentes($conn); $incoterms = obtenerIncoterms($conn); $paises = obtenerPaises($conn); $transportistas = obtenerTransportistas($conn); $choferes = obtenerChoferes($conn); $unidades_medida = obtenerUnidadesMedida($conn); include __DIR__ . '/../../views/templates_rapidos/editar.php'; } function actualizar() { if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } $conn = getConnection(); $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; $id = $_POST['id'] ?? null; $nombre = trim($_POST['nombre'] ?? ''); $descripcion = trim($_POST['descripcion'] ?? ''); $icono = trim($_POST['icono'] ?? '🏢'); if (!$id || !is_numeric($id)) { die("❌ ID inválido."); } // Configuración del template $config = [ 'tipo_moneda' => $_POST['tipo_moneda'] ?? '', 'incoterm' => $_POST['incoterm'] ?? '', 'vinculacion' => $_POST['vinculacion'] ?? '', 'pais_proveedor' => $_POST['pais_proveedor'] ?? '', 'pais_proveedor_texto' => $_POST['pais_proveedor_texto'] ?? '', 'anexo22_apendice' => $_POST['anexo22_apendice'] ?? '', 'patente' => $_POST['patente'] ?? '', 'transportista_id' => $_POST['transportista_id'] ?? '', 'chofer_id' => $_POST['chofer_id'] ?? '', 'tasa_preferencial' => $_POST['tasa_preferencial'] ?? '', 'unidad_comercial_id' => $_POST['unidad_comercial_id'] ?? '' ]; $config_json = json_encode($config, JSON_UNESCAPED_UNICODE); // Validaciones if (empty($nombre)) { die("❌ El nombre del template es obligatorio."); } // Verificar permisos $sqlCheck = "SELECT id FROM dbo.templates_rapidos WHERE id = ? AND (id_usuario_creador = ? OR id_agencia = ?)"; $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$id, $id_usuario, $id_agencia]); $exists = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC); if (!$exists) { die("❌ Template no encontrado o sin permisos para editarlo."); } $sql = "UPDATE dbo.templates_rapidos SET nombre = ?, descripcion = ?, icono = ?, config_json = ?, tipo_moneda = ?, incoterm = ?, vinculacion = ?, pais_proveedor = ?, tasa_preferencial = ?, fecha_modificacion = GETDATE() WHERE id = ?"; $params = [ $nombre, $descripcion, $icono, $config_json, $config['tipo_moneda'], $config['incoterm'], $config['vinculacion'] ?: null, $config['pais_proveedor'], $config['tasa_preferencial'], $id ]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { die("❌ Error al actualizar template: " . print_r(sqlsrv_errors(), true)); } header('Location: /IMPORTADORES/templates_rapidos/lista?updated=ok'); exit; } function eliminar() { if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; } $id = $_GET['id'] ?? null; if (!$id || !is_numeric($id)) { die("❌ ID inválido."); } $conn = getConnection(); $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; // Verificar permisos $sqlCheck = "SELECT id FROM dbo.templates_rapidos WHERE id = ? AND (id_usuario_creador = ? OR id_agencia = ?)"; $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$id, $id_usuario, $id_agencia]); $exists = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC); if (!$exists) { die("❌ Template no encontrado o sin permisos para eliminarlo."); } $sql = "UPDATE dbo.templates_rapidos SET activo = 0 WHERE id = ?"; $stmt = sqlsrv_query($conn, $sql, [$id]); if ($stmt === false) { die("❌ Error al eliminar template: " . print_r(sqlsrv_errors(), true)); } header('Location: /IMPORTADORES/templates_rapidos/lista?deleted=ok'); exit; } function ajax_lista() { if (!($_SESSION['usuario_id'] ?? false)) { http_response_code(403); echo json_encode([]); exit; } $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; $conn = getConnection(); // Parámetros de DataTables $draw = intval($_GET['draw'] ?? 0); $start = intval($_GET['start'] ?? 0); $length = intval($_GET['length'] ?? 10); $search = $_GET['search']['value'] ?? ''; // Construir condiciones de filtro $where = "activo = 1 AND (id_agencia IS NULL OR id_agencia = ? OR id_usuario_creador = ?)"; $params = [$id_agencia, $id_usuario]; if ($search !== '') { $where .= " AND (nombre LIKE ? OR descripcion LIKE ?)"; $like = "%{$search}%"; $params = array_merge($params, [$like, $like]); } // Total registros filtrados $sqlFiltered = "SELECT COUNT(*) AS total FROM dbo.templates_rapidos WHERE $where"; $stmtF = sqlsrv_query($conn, $sqlFiltered, $params); $rowF = sqlsrv_fetch_array($stmtF, SQLSRV_FETCH_ASSOC); $recordsFiltered = (int)($rowF['total'] ?? 0); // Total registros sin filtro $sqlTotal = "SELECT COUNT(*) AS total FROM dbo.templates_rapidos WHERE activo = 1 AND (id_agencia IS NULL OR id_agencia = ? OR id_usuario_creador = ?)"; $stmtT = sqlsrv_query($conn, $sqlTotal, [$id_agencia, $id_usuario]); $rowT = sqlsrv_fetch_array($stmtT, SQLSRV_FETCH_ASSOC); $recordsTotal = (int)($rowT['total'] ?? 0); // Consulta principal con paginación $sql = "SELECT t.id, t.nombre, t.descripcion, t.icono, t.tipo_moneda, t.incoterm, t.vinculacion, t.pais_proveedor, t.tasa_preferencial, t.fecha_creacion, u.nombre_usuario AS usuario_creador, CASE WHEN t.id_agencia IS NULL THEN 'Sistema' ELSE a.nombre END AS ambito FROM dbo.templates_rapidos t LEFT JOIN dbo.usuarios u ON t.id_usuario_creador = u.id LEFT JOIN dbo.agencias a ON t.id_agencia = a.id WHERE $where ORDER BY t.fecha_creacion DESC OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; $paramsData = array_merge($params, [$start, $length]); $stmt = sqlsrv_query($conn, $sql, $paramsData); $data = []; while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $fecha = $row['fecha_creacion'] instanceof DateTime ? $row['fecha_creacion']->format('d/m/Y H:i') : 'N/A'; $data[] = [ 'id' => $row['id'], 'icono' => htmlspecialchars($row['icono'] ?? '🏢'), 'nombre' => htmlspecialchars($row['nombre']), 'descripcion' => htmlspecialchars($row['descripcion'] ?? ''), 'tipo_moneda' => htmlspecialchars($row['tipo_moneda'] ?? ''), 'incoterm' => htmlspecialchars($row['incoterm'] ?? ''), 'pais_proveedor' => htmlspecialchars($row['pais_proveedor'] ?? ''), 'ambito' => htmlspecialchars($row['ambito'] ?? ''), 'usuario_creador' => htmlspecialchars($row['usuario_creador'] ?? ''), 'fecha_creacion' => $fecha ]; } echo json_encode([ 'draw' => $draw, 'recordsTotal' => $recordsTotal, 'recordsFiltered' => $recordsFiltered, 'data' => $data ]); } function ajax_obtener_templates_debug() { header('Content-Type: application/json; charset=UTF-8'); if (!($_SESSION['usuario_id'] ?? false)) { echo json_encode(['error' => 'Usuario no autenticado']); exit; } $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; try { $conn = getConnection(); // ✅ CONSULTA SIN FILTROS para debug $sql = "SELECT id, nombre, descripcion, icono, config_json, ISNULL(veces_usado, 0) as veces_usado, id_usuario_creador, id_agencia, activo, fecha_creacion FROM dbo.templates_rapidos ORDER BY fecha_creacion DESC"; $stmt = sqlsrv_query($conn, $sql); if ($stmt === false) { $errors = sqlsrv_errors(); echo json_encode([ 'error' => 'Error en consulta SQL', 'message' => $errors[0]['message'] ?? 'Error desconocido', 'sql_errors' => $errors ]); exit; } $templates = []; $debug_info = [ 'usuario_actual' => $id_usuario, 'agencia_actual' => $id_agencia, 'todos_los_templates' => [] ]; while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { // Info completa para debug $template_debug = [ 'id' => $row['id'], 'nombre' => $row['nombre'], 'id_usuario_creador' => $row['id_usuario_creador'], 'id_agencia' => $row['id_agencia'], 'activo' => $row['activo'], 'fecha_creacion' => $row['fecha_creacion'] instanceof DateTime ? $row['fecha_creacion']->format('Y-m-d H:i:s') : $row['fecha_creacion'], 'es_del_usuario_actual' => ($row['id_usuario_creador'] == $id_usuario), 'es_de_la_agencia' => ($row['id_agencia'] == $id_agencia), 'deberia_mostrarse' => ( $row['activo'] == 1 && ( $row['id_agencia'] === null || $row['id_agencia'] == $id_agencia || $row['id_usuario_creador'] == $id_usuario ) ) ]; $debug_info['todos_los_templates'][] = $template_debug; // Solo agregar a templates para mostrar si cumple condiciones if ($template_debug['deberia_mostrarse']) { $config = []; if (!empty($row['config_json'])) { $decoded = json_decode($row['config_json'], true); $config = is_array($decoded) ? $decoded : []; } $templates[] = [ 'id' => (int)$row['id'], 'nombre' => $row['nombre'], 'descripcion' => $row['descripcion'] ?? '', 'icono' => $row['icono'] ?? '📋', 'config' => $config, 'veces_usado' => (int)$row['veces_usado'], 'id_usuario_creador' => $row['id_usuario_creador'], 'es_mio' => ($row['id_usuario_creador'] == $id_usuario) ]; } } echo json_encode([ 'success' => true, 'count' => count($templates), 'templates' => $templates, 'debug_info' => $debug_info ], JSON_UNESCAPED_UNICODE); } catch (Exception $e) { echo json_encode([ 'error' => 'Error interno del servidor', 'message' => $e->getMessage() ]); } exit; } function ajax_obtener_templates() { // ✅ VERSIÓN CORREGIDA: Función simplificada sin filtros complejos header('Content-Type: application/json; charset=UTF-8'); if (!($_SESSION['usuario_id'] ?? false)) { http_response_code(403); echo json_encode(['error' => 'Usuario no autenticado', 'templates' => []]); exit; } $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; try { $conn = getConnection(); // ✅ CONSULTA SIMPLIFICADA: Mostrar todos los templates activos del usuario o agencia $sql = "SELECT id, nombre, descripcion, icono, config_json, ISNULL(veces_usado, 0) as veces_usado, id_usuario_creador, id_agencia FROM dbo.templates_rapidos WHERE activo = 1 AND (id_usuario_creador = ? OR id_agencia = ? OR id_agencia IS NULL) ORDER BY CASE WHEN id_usuario_creador = ? THEN 0 ELSE 1 END, veces_usado DESC, nombre ASC"; $params = [$id_usuario, $id_agencia, $id_usuario]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { $errors = sqlsrv_errors(); echo json_encode([ 'error' => 'Error en consulta SQL', 'message' => $errors[0]['message'] ?? 'Error desconocido', 'templates' => [] ]); exit; } $templates = []; $templates_personales = []; $templates_otros = []; while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { // Decodificar JSON con manejo de errores $config = []; if (!empty($row['config_json'])) { $decoded = json_decode($row['config_json'], true); $config = is_array($decoded) ? $decoded : []; } $template = [ 'id' => (int)$row['id'], 'nombre' => $row['nombre'], 'descripcion' => $row['descripcion'] ?? '', 'icono' => $row['icono'] ?? '📋', 'config' => $config, 'veces_usado' => (int)$row['veces_usado'], 'id_usuario_creador' => $row['id_usuario_creador'], 'id_agencia' => $row['id_agencia'], 'es_mio' => ($row['id_usuario_creador'] == $id_usuario), 'ambito' => ($row['id_usuario_creador'] == $id_usuario) ? 'personal' : (($row['id_agencia'] == $id_agencia) ? 'agencia' : 'sistema') ]; // Separar templates personales de otros if ($template['es_mio']) { $templates_personales[] = $template; } else { $templates_otros[] = $template; } $templates[] = $template; } // Respuesta con información detallada echo json_encode([ 'success' => true, 'count' => count($templates), 'count_personales' => count($templates_personales), 'count_otros' => count($templates_otros), 'usuario_id' => $id_usuario, 'agencia_id' => $id_agencia, 'templates' => $templates, 'templates_personales' => $templates_personales, 'templates_otros' => $templates_otros ], JSON_UNESCAPED_UNICODE); } catch (Exception $e) { echo json_encode([ 'error' => 'Error interno del servidor', 'message' => $e->getMessage(), 'templates' => [] ]); } exit; } function ajax_lista_por_seccion() { if (!($_SESSION['usuario_id'] ?? false)) { die(json_encode(['error' => 'No autorizado'])); } $conn = getConnection(); $id_usuario = $_SESSION['usuario_id']; $id_agencia = $_SESSION['id_agencia_en_uso'] ?? null; $seccion = $_GET['seccion'] ?? 'personal'; $data = []; try { switch($seccion) { case 'personal': // Solo templates creados por el usuario actual $sql = "SELECT id, nombre, descripcion, icono, config_json, veces_usado, fecha_creacion, id_usuario_creador FROM dbo.templates_rapidos WHERE id_usuario_creador = ? AND estado = 1 ORDER BY veces_usado DESC, fecha_creacion DESC"; $params = [$id_usuario]; break; case 'agencia': // Templates de la agencia (excluyendo los personales ya mostrados) $sql = "SELECT id, nombre, descripcion, icono, config_json, veces_usado, fecha_creacion, id_usuario_creador FROM dbo.templates_rapidos WHERE id_agencia = ? AND id_usuario_creador != ? AND estado = 1 ORDER BY veces_usado DESC, fecha_creacion DESC"; $params = [$id_agencia, $id_usuario]; break; case 'global': // Templates globales del sistema (solo si se solicitan explícitamente) $sql = "SELECT id, nombre, descripcion, icono, config_json, veces_usado, fecha_creacion, id_usuario_creador FROM dbo.templates_rapidos WHERE id_agencia IS NULL AND id_usuario_creador IS NULL AND estado = 1 ORDER BY veces_usado DESC, fecha_creacion DESC"; $params = []; break; default: throw new Exception('Sección inválida'); } $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { throw new Exception('Error en consulta: ' . print_r(sqlsrv_errors(), true)); } while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { // Formatear fecha $fecha = $row['fecha_creacion'] instanceof DateTime ? $row['fecha_creacion']->format('d/m/Y') : date('d/m/Y', strtotime($row['fecha_creacion'])); // Determinar acciones según el tipo de template $acciones = ''; $esPropio = ($row['id_usuario_creador'] == $id_usuario); $esAgencia = ($seccion === 'agencia'); $esGlobal = ($seccion === 'global'); if ($esPropio) { $acciones = '
'; } elseif ($esAgencia) { $acciones = '