Part spawns inside ground

my part spwans inside the ground when i use my building system

client :

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local RE = ReplicatedStorage.RemoteFunction

local Buildings = ReplicatedStorage.Buildings
local Stuff = workspace.Stuff
local plr = Players.LocalPlayer
local mouse = plr:GetMouse()

local building = false
local currentModel = nil
local canPlace = nil
local debounce = false
local rotationY = 0 -- Track Y-axis rotation

local ROTATION_INCREMENT = 15 -- Rotation step in degrees

local function updateModelPosition()
	if not building or not currentModel then return end

	local mouseRay = mouse.UnitRay
	local castRay = Ray.new(mouseRay.Origin, mouseRay.Direction * 1000)
	local ignoreList = {plr.Character, currentModel}
	local hit, position = workspace:FindPartOnRayWithIgnoreList(castRay, ignoreList, true, true)

	if hit and (hit:IsA("BasePart") or hit:IsA("Terrain")) then
		canPlace = true
		for _, part in pairs(currentModel:GetDescendants()) do
			if part:IsA("BasePart") then
				part.BrickColor = BrickColor.new("Bright blue")
			end
		end
		-- Adjust height based on model bounding box
		local modelHeight = currentModel:GetExtentsSize().Y / 2
		position = Vector3.new(position.X, position.Y + modelHeight, position.Z)
	else
		canPlace = false
		for _, part in pairs(currentModel:GetDescendants()) do
			if part:IsA("BasePart") then
				part.BrickColor = BrickColor.new("Bright red")
			end
		end
	end

	-- Apply rotation and position
	local rotation = CFrame.Angles(0, math.rad(rotationY), 0)
	local newCFrame = CFrame.new(position)
	currentModel:SetPrimaryPartCFrame(newCFrame * rotation)
end

local function startBuilding(model)
	if building then return end

	if not model or not model:IsA("Model") then
		warn("Invalid model passed to startBuilding!")
		return
	end

	building = true
	currentModel = model:Clone()

	if not currentModel.Name then
		warn("Model does not have a valid Name!")
		return
	end

	currentModel.Parent = Stuff
	currentModel.PrimaryPart = currentModel:FindFirstChild("PrimaryPart") or currentModel:FindFirstChildWhichIsA("BasePart")
	currentModel:SetPrimaryPartCFrame(plr.Character.HumanoidRootPart.CFrame)
	currentModel.PrimaryPart.CanCollide = false

	for _, part in pairs(currentModel:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Material = Enum.Material.Neon
			part.Transparency = 0.5
		end
	end

	rotationY = 0 -- Reset rotation

	if not updateConnection then
		updateConnection = RunService.RenderStepped:Connect(updateModelPosition)
	end
end

local function stopBuilding()
	if not building or debounce then return end
	if currentModel and canPlace then
		if not currentModel.Name then
			warn("currentModel does not have a valid Name!")
			return
		end

		debounce = true
		local modelCFrame = currentModel.PrimaryPart.CFrame

		-- Ensure we are passing the model's Name
		RE:InvokeServer(currentModel.Name, modelCFrame)
		currentModel:Destroy()
		currentModel = nil
		building = false
		debounce = false

		if updateConnection then
			updateConnection:Disconnect()
			updateConnection = nil
		end
	end
end

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then return end

	if input.KeyCode == Enum.KeyCode.R then
		rotationY = rotationY + ROTATION_INCREMENT
	elseif input.KeyCode == Enum.KeyCode.T then
		rotationY = rotationY - ROTATION_INCREMENT
	end

	if input.UserInputType == Enum.UserInputType.MouseButton1 and building then
		stopBuilding()
	end
end)

for _, button in pairs(script.Parent:GetChildren()) do
	if button:IsA("ImageButton") then
		button.MouseButton1Click:Connect(function()
			if not building then
				local modelName = button.Value.Value.Name
				local model = Buildings:FindFirstChild(modelName)
				if model then
					startBuilding(model)
				end
			end
		end)
	end
end

serverside :

RE.OnServerInvoke = function(player, modelName, cframe)
	print("Received modelName:", modelName, "with CFrame:", cframe)

	if not modelName or typeof(modelName) ~= "string" then
		warn("Invalid modelName received!")
		return
	end

	local model = Buildings:FindFirstChild(modelName)
	if not model then
		warn("Model not found in Buildings:", modelName)
		return
	end

	local newModel = model:Clone()
	newModel.PrimaryPart = newModel.PrimaryPart or newModel:FindFirstChildWhichIsA("BasePart")

	if not newModel.PrimaryPart then
		warn("No PrimaryPart found for model:", modelName)
		return
	end

	-- Perform a downward raycast to find the exact ground position
	local rayOrigin = cframe.Position
	local rayDirection = Vector3.new(0, -1000, 0) -- Cast ray down 1000 studs
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {workspace.Stuff, newModel}
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

	local result = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

	if result then
		-- Use the surface's Y-position for proper placement
		local surfaceY = result.Position.Y
		local modelHeight = newModel:GetExtentsSize().Y / 2
		local adjustedCFrame = CFrame.new(cframe.Position.X, surfaceY + modelHeight, cframe.Position.Z)

		newModel:SetPrimaryPartCFrame(adjustedCFrame)
		newModel.Parent = workspace.Stuff

		-- Anchor parts after placing
		RunService.Heartbeat:Wait()
		for _, part in pairs(newModel:GetDescendants()) do
			if part:IsA("BasePart") then
				part.Anchored = true
			end
		end

		saveBlockData(player, modelName, adjustedCFrame) -- Save the corrected CFrame
	else
		warn("No surface found below the placement position!")
		return
	end
end