0) { $_SESSION['import_errors'] = $errors; header('Location: /IMPORTADORES/transportistas/bulk_upload?status=error'); } else { $_SESSION['import_success'] = true; header('Location: /IMPORTADORES/transportistas/bulk_upload?status=ok'); } exit; } function bulk_upload() { include __DIR__ . '/../../views/transportistas/bulk_upload.php'; } function ajax_lista() { // 1) Autorización if (!($_SESSION['usuario_id'] ?? false)) { http_response_code(403); echo json_encode([]); exit; } $usr = $_SESSION['usuario_id']; $conn = getConnection(); // 2) Parámetros de DataTables $draw = intval($_GET['draw'] ?? 0); $start = intval($_GET['start'] ?? 0); $length = intval($_GET['length'] ?? 10); $search = $_GET['search']['value'] ?? ''; // Mapeo columnas - ahora incluimos el nombre de la ciudad $cols = ['t.id_transportista','t.clave_identificador','t.nombre','t.rfc','c.nombre','t.creado_en']; $orderColIdx = intval($_GET['order'][0]['column'] ?? 5); $orderDir = strtoupper($_GET['order'][0]['dir'] ?? 'ASC') === 'DESC' ? 'DESC' : 'ASC'; $orderCol = in_array($orderColIdx, range(0,5)) ? $cols[$orderColIdx] : 't.creado_en'; // 3) Total registros sin filtro $sqlTotal = "SELECT COUNT(*) AS total FROM dbo.transportistas WHERE id_usuario = ? AND activo = 1"; $stmt = sqlsrv_query($conn, $sqlTotal, [$usr]); $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); $recordsTotal = (int)$row['total']; // 4) Construir condiciones de filtro $where = "t.id_usuario = ? AND t.activo = 1 "; $params = [$usr]; if ($search !== '') { $where .= " AND ( t.nombre LIKE ? OR t.rfc LIKE ? OR c.nombre LIKE ? )"; $like = "%{$search}%"; $params = array_merge($params, array_fill(0, 3, $like)); } // 5) Total registros filtrados (CON JOIN) $sqlFiltered = " SELECT COUNT(*) AS total FROM dbo.transportistas t LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.estados e ON c.estado_id = e.id_estado LEFT JOIN dbo.paises p ON e.pais_id = p.id_pais WHERE $where "; $stmtF = sqlsrv_query($conn, $sqlFiltered, $params); $rowF = sqlsrv_fetch_array($stmtF, SQLSRV_FETCH_ASSOC); $recordsFiltered = (int)$rowF['total']; // 6) Datos de la página con JOIN completo $sqlData = " SELECT t.id_transportista, t.clave_identificador, t.nombre, t.rfc, COALESCE(c.nombre, 'Ciudad no encontrada') as ciudad_nombre, COALESCE(e.nombre, '') as estado_nombre, COALESCE(p.nombre, '') as pais_nombre, t.creado_en FROM dbo.transportistas t LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad LEFT JOIN dbo.estados e ON c.estado_id = e.id_estado LEFT JOIN dbo.paises p ON e.pais_id = p.id_pais WHERE $where ORDER BY $orderCol $orderDir OFFSET ? ROWS FETCH NEXT ? ROWS ONLY "; // agregar offset/limit al final $params[] = $start; $params[] = $length; $stmtD = sqlsrv_query($conn, $sqlData, $params); $data = []; while ($r = sqlsrv_fetch_array($stmtD, SQLSRV_FETCH_ASSOC)) { $data[] = [ $r['id_transportista'], $r['clave_identificador'], $r['nombre'], $r['rfc'], $r['ciudad_nombre'], // Ahora muestra el nombre real de la ciudad $r['creado_en'] instanceof DateTime ? $r['creado_en']->format('Y-m-d H:i') : '' ]; } // 7) Devolver JSON $response = [ "draw" => $draw, "recordsTotal" => $recordsTotal, "recordsFiltered" => $recordsFiltered, "data" => $data ]; $json = json_encode($response, JSON_UNESCAPED_UNICODE); if (json_last_error() !== JSON_ERROR_NONE) { http_response_code(500); echo json_encode(["error" => "JSON encoding error: " . json_last_error_msg()]); exit; } header('Content-Type: application/json; charset=UTF-8'); header('Cache-Control: no-cache, must-revalidate'); echo $json; exit; } function editar() { // 1) Verificar sesión if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; } $usr = $_SESSION['usuario_id']; // 2) Obtener el ID y validarlo $id = $_GET['id'] ?? null; if (!$id || !is_numeric($id)) { die("❌ ID de transportista inválido."); } $conn = getConnection(); // 3) Consultar el transportista (pertenece al usuario) $sql = "SELECT * FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?"; $stmt = sqlsrv_query($conn, $sql, [$id, $usr]); $t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); if (!$t) { die("❌ Transportista no encontrado o no autorizado."); } // 4) Cargar listas de países, estados y ciudades // --- Países --- $paises = []; $rs = sqlsrv_query($conn, "SELECT id_pais, nombre FROM dbo.paises ORDER BY nombre"); while ($r = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) { $paises[] = $r; } // --- Estados para el país actual --- $estados = []; $rs = sqlsrv_query($conn, "SELECT id_estado, nombre FROM dbo.estados WHERE pais_id = ? ORDER BY nombre", [$t['pais']]); while ($r = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) { $estados[] = $r; } // --- Ciudades para el estado actual --- $ciudades = []; $rs = sqlsrv_query($conn, "SELECT id_ciudad, nombre FROM dbo.ciudades WHERE estado_id = ? ORDER BY nombre", [$t['entidad_federativa']]); while ($r = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) { $ciudades[] = $r; } // 5) Renderizar la vista include __DIR__ . '/../../views/transportistas/editar.php'; } /** Procesa el POST de actualización **/ function actualizar() { if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } $usr = $_SESSION['usuario_id']; // 1) Capturar y validar datos $id = $_POST['id_transportista'] ?? null; $clave = trim($_POST['clave'] ?? ''); $nombre= trim($_POST['nombre'] ?? ''); $rfc = trim($_POST['rfc'] ?? ''); $curp = trim($_POST['curp'] ?? ''); $tel = trim($_POST['telefono'] ?? ''); $caat = trim($_POST['caat'] ?? ''); $pais = $_POST['pais'] ?? ''; $estado= $_POST['entidad'] ?? ''; $ciudad= $_POST['ciudad'] ?? ''; $dom = trim($_POST['domicilio'] ?? ''); if (!$id || !is_numeric($id) || $clave===''||$nombre===''||$rfc===''||$tel===''||$caat==='' || $pais===''||$estado===''||$ciudad===''||$dom==='' ) { die("❌ Faltan datos obligatorios."); } $conn = getConnection(); // 2) Verificar que exista y pertenezca al usuario $sqlChk = "SELECT COUNT(*) AS cnt FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?"; $stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]); $rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC); if ($rowChk['cnt'] == 0) { die("❌ Transportista no encontrado o no autorizado."); } // 3) Ejecutar UPDATE $sqlUpd = "UPDATE dbo.transportistas SET clave_identificador = ?, nombre = ?, rfc = ?, curp = ?, telefono = ?, caat = ?, pais = ?, entidad_federativa = ?, ciudad = ?, domicilio = ? WHERE id_transportista = ?"; $params = [ $clave, $nombre, $rfc, $curp, $tel, $caat, $pais, $estado, $ciudad, $dom, $id ]; $stmtUpd = sqlsrv_query($conn, $sqlUpd, $params); if ($stmtUpd === false) { die("❌ Error al actualizar: " . print_r(sqlsrv_errors(), true)); } // 4) Redirigir con éxito header("Location: /IMPORTADORES/transportistas/lista?edit=ok"); exit; } function eliminar() { if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; } $usr = $_SESSION['usuario_id']; $id = $_GET['id'] ?? null; if (!$id || !is_numeric($id)) { die("❌ ID inválido."); } $conn = getConnection(); // Verificar que el transportista exista y pertenezca al usuario $sqlChk = "SELECT COUNT(*) AS cnt FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?"; $stmtChk = sqlsrv_query($conn, $sqlChk, [$id, $usr]); $rowChk = sqlsrv_fetch_array($stmtChk, SQLSRV_FETCH_ASSOC); if ($rowChk['cnt'] == 0) { die("❌ Transportista no encontrado o no autorizado."); } // ELIMINACIÓN REAL - DELETE en lugar de UPDATE $sqlDel = "UPDATE dbo.transportistas SET activo = 0 WHERE id_transportista = ?"; $stmtDel = sqlsrv_query($conn, $sqlDel, [$id]); if ($stmtDel === false) { die("❌ Error al eliminar: " . print_r(sqlsrv_errors(), true)); } // Redirigir con parámetro para SweetAlert header("Location: /IMPORTADORES/transportistas/lista?deleted=ok"); exit; }