<?php
// Include header
require_once 'includes/header.php';
// Ensure the user is an admin or director
if (!isset($_SESSION['user_id']) || ($_SESSION['role'] !== 'admin' && $_SESSION['role'] !== 'director')) {
echo '<div class="alert alert-danger">Access denied. You need to be an administrator to access this page.</div>';
include 'includes/footer.php';
exit;
}
// Process payment verification
$success_message = '';
$error_message = '';
// Handle payment verification
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['verify_payment'])) {
$payment_id = $_POST['payment_id'] ?? 0;
if ($payment_id > 0) {
$verify_query = "UPDATE payments SET status = 'completed', verified_at = NOW(), marked_by = ? WHERE id = ?";
$stmt = $conn->prepare($verify_query);
$stmt->bind_param("ii", $_SESSION['user_id'], $payment_id);
if ($stmt->execute()) {
// Log the action
$log_message = "Payment ID #{$payment_id} verified by admin";
logger($_SESSION['user_id'], 'payment_verified', $log_message);
$success_message = "Payment has been verified successfully.";
} else {
$error_message = "Failed to verify payment: " . $conn->error;
}
}
}
// Process payment rejection
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['reject_payment'])) {
$payment_id = $_POST['payment_id'] ?? 0;
$rejection_reason = $_POST['rejection_reason'] ?? '';
if ($payment_id > 0) {
$reject_query = "UPDATE payments SET status = 'rejected', rejection_reason = ?, verified_at = NOW(), marked_by = ? WHERE id = ?";
$stmt = $conn->prepare($reject_query);
$stmt->bind_param("sii", $rejection_reason, $_SESSION['user_id'], $payment_id);
if ($stmt->execute()) {
// Log the action
$log_message = "Payment ID #{$payment_id} rejected by admin. Reason: " . $rejection_reason;
logger($_SESSION['user_id'], 'payment_rejected', $log_message);
$success_message = "Payment has been rejected.";
} else {
$error_message = "Failed to reject payment: " . $conn->error;
}
}
}
// Process new payment addition
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_payment'])) {
$user_id = $_POST['user_id'] ?? 0;
$course_id = $_POST['course_id'] ?? 0;
$amount = floatval($_POST['amount'] ?? 0);
$payment_method = $_POST['payment_method'] ?? '';
$transaction_id = $_POST['transaction_id'] ?? '';
$payment_details = $_POST['payment_details'] ?? '';
// Validation
$error = false;
if ($user_id <= 0) {
$error_message = "Invalid user selected.";
$error = true;
} else if ($course_id <= 0) {
$error_message = "Invalid course selected.";
$error = true;
} else if ($amount <= 0) {
$error_message = "Amount must be greater than zero.";
$error = true;
} else if (empty($payment_method)) {
$error_message = "Payment method is required.";
$error = true;
} else if (empty($transaction_id)) {
$error_message = "Transaction ID is required.";
$error = true;
}
if (!$error) {
// Check if transaction ID already exists
$check_query = "SELECT id FROM payments WHERE transaction_id = ?";
$stmt = $conn->prepare($check_query);
$stmt->bind_param("s", $transaction_id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$error_message = "Transaction ID already exists. Please use a unique transaction ID.";
} else {
// Insert payment
$insert_query = "INSERT INTO payments (user_id, course_id, amount, payment_method,
transaction_id, payment_details, payment_date, status, marked_by)
VALUES (?, ?, ?, ?, ?, ?, NOW(), 'completed', ?)";
$stmt = $conn->prepare($insert_query);
$stmt->bind_param("iidsssi", $user_id, $course_id, $amount, $payment_method,
$transaction_id, $payment_details, $_SESSION['user_id']);
if ($stmt->execute()) {
$success_message = "Payment of ₹" . number_format($amount, 2) . " has been added successfully.";
// Log the action
$log_message = "New payment of ₹" . number_format($amount, 2) . " added for User ID #{$user_id}, Course ID #{$course_id}";
logger($_SESSION['user_id'], 'payment_added', $log_message);
} else {
$error_message = "Failed to add payment: " . $conn->error;
}
}
}
}
// Get filter parameters
$status_filter = isset($_GET['status']) ? $_GET['status'] : '';
$method_filter = isset($_GET['payment_method']) ? $_GET['payment_method'] : '';
$start_date = isset($_GET['start_date']) ? $_GET['start_date'] : '';
$end_date = isset($_GET['end_date']) ? $_GET['end_date'] : '';
$search = isset($_GET['search']) ? $_GET['search'] : '';
// Build query based on filters
$query = "SELECT p.*,
u.first_name, u.last_name, u.email,
c.title as course_title,
a.first_name as admin_first_name, a.last_name as admin_last_name
FROM payments p
LEFT JOIN users u ON p.user_id = u.id
LEFT JOIN courses c ON p.course_id = c.id
LEFT JOIN users a ON p.marked_by = a.id
WHERE 1=1";
$params = [];
$param_types = "";
if (!empty($status_filter)) {
$query .= " AND p.status = ?";
$params[] = $status_filter;
$param_types .= "s";
}
if (!empty($method_filter)) {
$query .= " AND p.payment_method = ?";
$params[] = $method_filter;
$param_types .= "s";
}
if (!empty($start_date)) {
$query .= " AND DATE(p.payment_date) >= ?";
$params[] = $start_date;
$param_types .= "s";
}
if (!empty($end_date)) {
$query .= " AND DATE(p.payment_date) <= ?";
$params[] = $end_date;
$param_types .= "s";
}
if (!empty($search)) {
$search_param = "%$search%";
$query .= " AND (u.first_name LIKE ? OR u.last_name LIKE ? OR u.email LIKE ? OR
c.title LIKE ? OR p.transaction_id LIKE ? OR p.payment_details LIKE ?)";
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
$param_types .= "ssssss";
}
// Add order by clause
$query .= " ORDER BY p.payment_date DESC";
// Prepare and execute query
$stmt = $conn->prepare($query);
if (!empty($params)) {
$stmt->bind_param($param_types, ...$params);
}
$stmt->execute();
$result = $stmt->get_result();
$payments = [];
while ($row = $result->fetch_assoc()) {
$payments[] = $row;
}
// Calculate payment statistics
$total_payments = count($payments);
$total_amount = 0;
$completed_amount = 0;
$pending_amount = 0;
foreach ($payments as $payment) {
$total_amount += $payment['amount'];
if ($payment['status'] === 'completed' || $payment['status'] === 'verified') {
$completed_amount += $payment['amount'];
} else if ($payment['status'] === 'pending') {
$pending_amount += $payment['amount'];
}
}
// Get unique payment methods for filter
$methods_query = "SELECT DISTINCT payment_method FROM payments ORDER BY payment_method";
$methods_result = $conn->query($methods_query);
$payment_methods = [];
while ($method = $methods_result->fetch_assoc()) {
$payment_methods[] = $method['payment_method'];
}
// Get student list for payment form
$students_query = "SELECT id, first_name, last_name, email FROM users WHERE role = 'student' ORDER BY first_name, last_name";
$students_result = $conn->query($students_query);
$students = [];
while ($student = $students_result->fetch_assoc()) {
$students[] = $student;
}
// Get courses for payment form
$courses_query = "SELECT id, title FROM courses ORDER BY title";
$courses_result = $conn->query($courses_query);
$courses = [];
while ($course = $courses_result->fetch_assoc()) {
$courses[] = $course;
}
?>
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Payment Management</h1>
<button class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm" data-bs-toggle="modal" data-bs-target="#addPaymentModal">
<i class="fas fa-plus fa-sm text-white-50"></i> Add New Payment
</button>
</div>
<?php if (isset($success_message)): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?php echo $success_message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if (isset($error_message)): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?php echo $error_message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<!-- Statistics Cards -->
<div class="row">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Total Payments</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $total_payments; ?></div>
</div>
<div class="col-auto">
<i class="fas fa-calendar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Total Amount</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">₹<?php echo number_format($total_amount, 2); ?></div>
</div>
<div class="col-auto">
<i class="fas fa-rupee-sign fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Completed Amount</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">₹<?php echo number_format($completed_amount, 2); ?></div>
</div>
<div class="col-auto">
<i class="fas fa-check-circle fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Pending Amount</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">₹<?php echo number_format($pending_amount, 2); ?></div>
</div>
<div class="col-auto">
<i class="fas fa-clock fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filters Card -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Payment Filters</h6>
</div>
<div class="card-body">
<form method="get" action="" class="row">
<div class="col-md-2 mb-3">
<label for="status" class="form-label">Payment Status</label>
<select class="form-select" id="status" name="status">
<option value="">All Statuses</option>
<option value="pending" <?php echo ($status_filter === 'pending') ? 'selected' : ''; ?>>Pending</option>
<option value="completed" <?php echo ($status_filter === 'completed') ? 'selected' : ''; ?>>Completed</option>
<option value="rejected" <?php echo ($status_filter === 'rejected') ? 'selected' : ''; ?>>Rejected</option>
<option value="refunded" <?php echo ($status_filter === 'refunded') ? 'selected' : ''; ?>>Refunded</option>
</select>
</div>
<div class="col-md-2 mb-3">
<label for="payment_method" class="form-label">Payment Method</label>
<select class="form-select" id="payment_method" name="payment_method">
<option value="">All Methods</option>
<?php foreach ($payment_methods as $method): ?>
<option value="<?php echo $method; ?>" <?php echo ($method_filter === $method) ? 'selected' : ''; ?>>
<?php echo ucfirst($method); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2 mb-3">
<label for="start_date" class="form-label">Start Date</label>
<input type="date" class="form-control" id="start_date" name="start_date" value="<?php echo $start_date; ?>">
</div>
<div class="col-md-2 mb-3">
<label for="end_date" class="form-label">End Date</label>
<input type="date" class="form-control" id="end_date" name="end_date" value="<?php echo $end_date; ?>">
</div>
<div class="col-md-3 mb-3">
<label for="search" class="form-label">Search</label>
<input type="text" class="form-control" id="search" name="search"
placeholder="Student, course, transaction ID..." value="<?php echo htmlspecialchars($search); ?>">
</div>
<div class="col-md-1 mb-3 d-flex align-items-end">
<button type="submit" class="btn btn-primary w-100">Filter</button>
</div>
</form>
<?php if (!empty($status_filter) || !empty($method_filter) || !empty($start_date) || !empty($end_date) || !empty($search)): ?>
<div class="mt-2">
<a href="payments.php" class="btn btn-sm btn-outline-secondary">
<i class="fas fa-times"></i> Clear Filters
</a>
</div>
<?php endif; ?>
</div>
</div>
<!-- Payments Table -->
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">All Payments</h6>
<span class="badge bg-primary"><?php echo $total_payments; ?> record(s)</span>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="paymentsTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>ID</th>
<th>Date</th>
<th>Student</th>
<th>Course</th>
<th>Amount</th>
<th>Method</th>
<th>Transaction ID</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (count($payments) > 0): ?>
<?php foreach ($payments as $payment): ?>
<tr>
<td><?php echo $payment['id']; ?></td>
<td><?php echo date('M d, Y H:i', strtotime($payment['payment_date'])); ?></td>
<td>
<?php echo htmlspecialchars($payment['first_name'] . ' ' . $payment['last_name']); ?>
<small class="d-block text-muted"><?php echo $payment['email']; ?></small>
</td>
<td><?php echo htmlspecialchars($payment['course_title'] ?? 'N/A'); ?></td>
<td class="text-right">₹<?php echo number_format($payment['amount'], 2); ?></td>
<td>
<span class="badge bg-info">
<?php echo ucfirst($payment['payment_method']); ?>
</span>
</td>
<td>
<small><?php echo htmlspecialchars($payment['transaction_id']); ?></small>
</td>
<td>
<?php
$status_class = 'secondary';
if ($payment['status'] === 'completed') {
$status_class = 'success';
} else if ($payment['status'] === 'pending') {
$status_class = 'warning';
} else if ($payment['status'] === 'rejected') {
$status_class = 'danger';
} else if ($payment['status'] === 'refunded') {
$status_class = 'info';
}
?>
<span class="badge bg-<?php echo $status_class; ?>">
<?php echo ucfirst($payment['status']); ?>
</span>
</td>
<td>
<button class="btn btn-sm btn-info view-payment-btn"
data-payment-id="<?php echo $payment['id']; ?>"
data-bs-toggle="modal"
data-bs-target="#viewPaymentModal">
<i class="fas fa-eye"></i>
</button>
<?php if ($payment['status'] === 'pending'): ?>
<button class="btn btn-sm btn-success verify-payment-btn"
data-payment-id="<?php echo $payment['id']; ?>"
data-bs-toggle="modal"
data-bs-target="#verifyPaymentModal">
<i class="fas fa-check"></i>
</button>
<button class="btn btn-sm btn-danger reject-payment-btn"
data-payment-id="<?php echo $payment['id']; ?>"
data-bs-toggle="modal"
data-bs-target="#rejectPaymentModal">
<i class="fas fa-times"></i>
</button>
<?php endif; ?>
<?php if ($payment['status'] === 'completed' && $payment['user_id'] > 0 && $payment['course_id'] > 0): ?>
<a href="student/view_receipt.php?payment_id=<?php echo $payment['id']; ?>"
class="btn btn-sm btn-primary" target="_blank">
<i class="fas fa-file-invoice"></i>
</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="9" class="text-center">No payments found.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
<!-- Add Payment Modal -->
<div class="modal fade" id="addPaymentModal" tabindex="-1" aria-labelledby="addPaymentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="addPaymentModalLabel">Add New Payment</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="">
<div class="modal-body">
<div class="row mb-3">
<div class="col-md-6">
<label for="user_id" class="form-label">Student</label>
<select class="form-select" id="user_id" name="user_id" required>
<option value="">Select Student</option>
<?php foreach ($students as $student): ?>
<option value="<?php echo $student['id']; ?>">
<?php echo htmlspecialchars($student['first_name'] . ' ' . $student['last_name']); ?> (<?php echo $student['email']; ?>)
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label for="course_id" class="form-label">Course</label>
<select class="form-select" id="course_id" name="course_id" required>
<option value="">Select Course</option>
<?php foreach ($courses as $course): ?>
<option value="<?php echo $course['id']; ?>">
<?php echo htmlspecialchars($course['title']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="amount" class="form-label">Amount (₹)</label>
<input type="number" class="form-control" id="amount" name="amount" step="0.01" min="0.01" required>
</div>
<div class="col-md-6">
<label for="payment_method" class="form-label">Payment Method</label>
<select class="form-select" id="payment_method" name="payment_method" required>
<option value="">Select Method</option>
<option value="cash">Cash</option>
<option value="bank_transfer">Bank Transfer</option>
<option value="upi">UPI</option>
<option value="check">Check/Cheque</option>
<option value="card">Credit/Debit Card</option>
<option value="online">Online Payment</option>
<option value="razorpay">Razorpay</option>
</select>
</div>
</div>
<div class="mb-3">
<label for="transaction_id" class="form-label">Transaction ID</label>
<input type="text" class="form-control" id="transaction_id" name="transaction_id" required>
<small class="form-text text-muted">
Unique identifier for this payment. For cash payments, use receipt number or date-studentID.
</small>
</div>
<div class="mb-3">
<label for="payment_details" class="form-label">Payment Details (Optional)</label>
<textarea class="form-control" id="payment_details" name="payment_details" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="add_payment" class="btn btn-primary">Add Payment</button>
</div>
</form>
</div>
</div>
</div>
<!-- View Payment Modal -->
<div class="modal fade" id="viewPaymentModal" tabindex="-1" aria-labelledby="viewPaymentModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-info text-white">
<h5 class="modal-title" id="viewPaymentModalLabel">Payment Details</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="paymentDetailsContent">
<div class="text-center p-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="mt-2">Loading payment details...</p>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Verify Payment Modal -->
<div class="modal fade" id="verifyPaymentModal" tabindex="-1" aria-labelledby="verifyPaymentModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-success text-white">
<h5 class="modal-title" id="verifyPaymentModalLabel">Verify Payment</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="">
<div class="modal-body">
<p>Are you sure you want to verify this payment? This action cannot be undone.</p>
<input type="hidden" id="verify_payment_id" name="payment_id" value="">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="verify_payment" class="btn btn-success">Verify Payment</button>
</div>
</form>
</div>
</div>
</div>
<!-- Reject Payment Modal -->
<div class="modal fade" id="rejectPaymentModal" tabindex="-1" aria-labelledby="rejectPaymentModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-danger text-white">
<h5 class="modal-title" id="rejectPaymentModalLabel">Reject Payment</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="">
<div class="modal-body">
<p>Are you sure you want to reject this payment?</p>
<input type="hidden" id="reject_payment_id" name="payment_id" value="">
<div class="mb-3">
<label for="rejection_reason" class="form-label">Reason for Rejection</label>
<textarea class="form-control" id="rejection_reason" name="rejection_reason" rows="3" required></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="reject_payment" class="btn btn-danger">Reject Payment</button>
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function() {
// Initialize DataTable
$('#paymentsTable').DataTable({
"order": [[0, "desc"]],
"pageLength": 25
});
// Select2 for dropdowns
$('#user_id, #course_id').select2({
dropdownParent: $('#addPaymentModal')
});
// View payment details
$('.view-payment-btn').on('click', function() {
var paymentId = $(this).data('payment-id');
// Reset content
$('#paymentDetailsContent').html('<div class="text-center p-4"><div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div><p class="mt-2">Loading payment details...</p></div>');
// Load payment details via AJAX
$.ajax({
url: 'ajax/get_payment_details.php',
type: 'GET',
data: { payment_id: paymentId },
success: function(response) {
$('#paymentDetailsContent').html(response);
},
error: function() {
$('#paymentDetailsContent').html('<div class="alert alert-danger">Failed to load payment details.</div>');
}
});
});
// Set payment ID for verification
$('.verify-payment-btn').on('click', function() {
var paymentId = $(this).data('payment-id');
$('#verify_payment_id').val(paymentId);
});
// Set payment ID for rejection
$('.reject-payment-btn').on('click', function() {
var paymentId = $(this).data('payment-id');
$('#reject_payment_id').val(paymentId);
});
});
</script>
<?php
// Include footer
require_once 'includes/footer.php';
?>