2 * 1024 * 1024) { die("❌ La imagen no debe exceder 2 MB."); } $uploadDir = __DIR__ . '/../../public/uploads/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } $dest = $uploadDir . 'transporte_' . uniqid() . ".{$ext}"; if (move_uploaded_file($_FILES['foto']['tmp_name'], $dest)) { $fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest); } else { error_log("Error al mover archivo en guardar(): {$dest}"); die("❌ Error al subir la imagen."); } } // Insertar el nuevo transporte $sql = "INSERT INTO dbo.transportes (vehiculo, identificador_fiscal, foto_url, status, id_transportista) VALUES (?, ?, ?, 1, ?)"; $params = [$vehiculo, $identFiscal, $fotoUrl, $idTrans]; $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { $errors = sqlsrv_errors(); error_log("Error SQL en guardar transporte: " . print_r($errors, true)); die("❌ Error al guardar: " . $errors[0]['message']); } // Verificar que se insertó correctamente $rowsAffected = sqlsrv_rows_affected($stmt); if ($rowsAffected === 0) { die("❌ No se pudo crear el registro."); } header('Location: /IMPORTADORES/transportes/lista?created=ok'); exit; } /** Formulario de edición **/ 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(); // Validar pertenencia igual que en index() $sql = "SELECT t.*, tr.nombre AS transportista FROM dbo.transportes t JOIN dbo.transportistas tr ON t.id_transportista = tr.id_transportista WHERE t.id_transporte = ? AND tr.id_usuario = ? AND t.status = 1 "; $stmt = sqlsrv_query($conn, $sql, [$id, $_SESSION['usuario_id']]); $t = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC); if (!$t) die("❌ Transporte no encontrado o no autorizado."); // Mismo select de transportistas que en crear() $sql2 = "SELECT t.id_transportista, t.clave_identificador, t.nombre, t.ciudad, t.domicilio, c.nombre AS ciudad_nombre FROM dbo.transportistas t LEFT JOIN dbo.ciudades c ON t.ciudad = c.id_ciudad WHERE id_usuario = ? AND activo = 1 ORDER BY nombre "; $stmt2 = sqlsrv_query($conn, $sql2, [$_SESSION['usuario_id']]); $transportistas = []; while ($r = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC)) { $transportistas[] = $r; } include __DIR__ . '/../../views/transportes/editar.php'; } /** Procesa la actualización **/ function actualizar() { if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } $id = $_POST['id_transporte'] ?? null; $vehiculo = trim($_POST['vehiculo'] ?? ''); $identFiscal = trim($_POST['identificador_fiscal'] ?? ''); $idTrans = $_POST['id_transportista'] ?? null; if (!$id || !is_numeric($id) || $vehiculo === '' || $identFiscal === '' || !$idTrans) { die("❌ Faltan datos."); } $conn = getConnection(); // Antes del UPDATE, validar que el transporte pertenece al usuario $sqlCheck = "SELECT 1 FROM dbo.transportes t JOIN dbo.transportistas tr ON t.id_transportista = tr.id_transportista wHERE t.id_transporte = ? AND tr.id_usuario = ?"; $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$id, $_SESSION['usuario_id']]); if ($stmtCheck === false) { $errors = sqlsrv_errors(); error_log("Error SQL al validar transporte: " . print_r($errors, true)); die("❌ Error en la validación SQL."); } if (!sqlsrv_fetch($stmtCheck)) { die("❌ No autorizado para modificar este transporte."); } // —– Manejo de nueva foto —– $fotoUrl = null; if (isset($_FILES['foto']) && $_FILES['foto']['error'] === UPLOAD_ERR_OK) { $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp']; $ext = strtolower(pathinfo($_FILES['foto']['name'], PATHINFO_EXTENSION)); if (!in_array($ext, $allowedExtensions)) { die("❌ Formato de imagen no válido."); } $dest = __DIR__ . '/../../public/uploads/transporte_'.uniqid().".{$ext}"; if (!is_dir(dirname($dest))) { mkdir(dirname($dest), 0755, true); } if (move_uploaded_file($_FILES['foto']['tmp_name'], $dest)) { $fotoUrl = "/IMPORTADORES/public/uploads/" . basename($dest); } else { error_log("Error al mover archivo en actualizar(): {$dest}"); die("❌ Error al subir la imagen."); } } // —– Construye el UPDATE dinámico —– if ($fotoUrl) { $sql = "UPDATE dbo.transportes SET vehiculo = ?, identificador_fiscal = ?, id_transportista = ?, foto_url = ? WHERE id_transporte = ? "; $params = [$vehiculo, $identFiscal, $idTrans, $fotoUrl, $id]; } else { $sql = "UPDATE dbo.transportes SET vehiculo = ?, identificador_fiscal = ?, id_transportista = ? WHERE id_transporte = ? "; $params = [$vehiculo, $identFiscal, $idTrans, $id]; } $stmt = sqlsrv_query($conn, $sql, $params); if ($stmt === false) { $errors = sqlsrv_errors(); error_log("Error SQL en actualizar transporte: " . print_r($errors, true)); die("❌ Error al actualizar: " . $errors[0]['message']); } // Verificar si se afectó alguna fila $rowsAffected = sqlsrv_rows_affected($stmt); if ($rowsAffected === 0) { die("❌ No se pudo actualizar el registro."); } header('Location: /IMPORTADORES/transportes/lista?updated=ok'); exit; } /** “Soft-delete” (status = 0) **/ 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(); $sql = "UPDATE dbo.transportes SET status = 0 WHERE id_transporte = ?"; $stmt = sqlsrv_query($conn, $sql, [$id]); if ($stmt === false) { die("❌ Error al eliminar: ".print_r(sqlsrv_errors(),true)); } header('Location: /IMPORTADORES/transportes/lista?deleted=ok'); exit; } /** Formulario de importación masiva **/ function masivo() { if (!($_SESSION['usuario_id'] ?? false)) { header('Location: /IMPORTADORES/login'); exit; } include __DIR__ . '/../../views/transportes/importar_masivo.php'; } /** Procesa la importación masiva desde CSV **/ function importarGuardar() { if (!($_SESSION['usuario_id'] ?? false)) { die("⚠️ No autorizado."); } // Validar subida del archivo if (!isset($_FILES['csv']) || $_FILES['csv']['error'] !== UPLOAD_ERR_OK) { $_SESSION['import_result'] = [ 'imported' => 0, 'errors' => ["Error al subir el archivo CSV."] ]; header('Location: /IMPORTADORES/transportes/importar'); exit; } $conn = getConnection(); $tmp = $_FILES['csv']['tmp_name']; $handle = fopen($tmp, 'r'); $headers = fgetcsv($handle, 1000, ','); $usr = $_SESSION['usuario_id']; $imported = 0; $errors = []; $row = 1; while (($data = fgetcsv($handle, 1000, ',')) !== false) { $row++; if (count($data) < 3) { $errors[] = "Fila $row: formato incorrecto."; continue; } list($vehiculo, $identFiscal, $idTrans) = array_map('trim', $data); // Validaciones básicas if ($vehiculo === '' || $identFiscal === '' || !is_numeric($idTrans)) { $errors[] = "Fila $row: datos incompletos o inválidos."; continue; } // Verificar que el transportista pertenezca al usuario $sqlCheck = "SELECT COUNT(*) AS cnt FROM dbo.transportistas WHERE id_transportista = ? AND id_usuario = ?"; $stmtCheck = sqlsrv_query($conn, $sqlCheck, [$idTrans, $usr]); $rCheck = sqlsrv_fetch_array($stmtCheck, SQLSRV_FETCH_ASSOC); if ($rCheck['cnt'] == 0) { $errors[] = "Fila $row: transportista $idTrans no válido."; continue; } // Insertar sin foto $sql = "INSERT INTO dbo.transportes (vehiculo, identificador_fiscal, foto_url, status, id_transportista) VALUES (?, ?, NULL, 1, ?)"; $stmt = sqlsrv_query($conn, $sql, [$vehiculo, $identFiscal, $idTrans]); if ($stmt === false) { $errors[] = "Fila $row: error al insertar."; continue; } $imported++; } fclose($handle); // Guardar resultado en sesión y redirigir de vuelta al formulario $_SESSION['import_result'] = [ 'imported' => $imported, 'errors' => $errors ]; header('Location: /IMPORTADORES/transportes/masivo'); exit; }