candidate_id $user = get_user(); if (!$election_id || empty($votes)) { die("Invalid submission."); } try { $pdo = db(); $pdo->beginTransaction(); // 1. Verify election is ongoing $eStmt = $pdo->prepare("SELECT status FROM elections WHERE id = ?"); $eStmt->execute([$election_id]); if ($eStmt->fetchColumn() !== 'Ongoing') { throw new Exception("Election is not ongoing."); } // 2. Verify user hasn't voted yet $vCheck = $pdo->prepare("SELECT COUNT(*) FROM votes WHERE election_id = ? AND voter_id = ?"); $vCheck->execute([$election_id, $user['id']]); if ($vCheck->fetchColumn() > 0) { throw new Exception("You have already cast your vote for this election."); } // 3. Insert votes $stmt = $pdo->prepare("INSERT INTO votes (id, election_id, position_id, candidate_id, voter_id, ip_address, user_agent) VALUES (?, ?, ?, ?, ?, ?, ?)"); foreach ($votes as $position_id => $candidate_id) { $vote_id = uuid(); $stmt->execute([ $vote_id, $election_id, $position_id, $candidate_id, $user['id'], $_SERVER['REMOTE_ADDR'] ?? 'unknown', $_SERVER['HTTP_USER_AGENT'] ?? 'unknown' ]); } audit_log('Cast ballot', 'elections', $election_id); $pdo->commit(); header("Location: ../view_results.php?id=$election_id&success=vote_cast"); exit; } catch (Exception $e) { if ($pdo->inTransaction()) $pdo->rollBack(); die("Error casting vote: " . $e->getMessage()); } }