<?php
// Start output buffering to prevent headers already sent error
ob_start();
// Include header
include_once 'includes/header.php';
// Get student ID from session
$student_id = $_SESSION['user_id'];
$success_message = '';
$error_message = '';
// Handle flash messages
if (isset($_SESSION['success_message'])) {
$success_message = $_SESSION['success_message'];
unset($_SESSION['success_message']);
}
if (isset($_SESSION['error_message'])) {
$error_message = $_SESSION['error_message'];
unset($_SESSION['error_message']);
}
// Get payment gateway settings
$settings_query = "SELECT * FROM site_settings WHERE setting_key IN ('razorpay_key_id', 'razorpay_key_secret', 'payment_upi_id', 'institute_name', 'payment_qr_image')";
$settings_result = $conn->query($settings_query);
$settings = [];
if ($settings_result) {
while ($row = $settings_result->fetch_assoc()) {
$settings[$row['setting_key']] = $row['setting_value'];
}
}
$razorpay_key_id = $settings['razorpay_key_id'] ?? 'rzp_test_YourRazorpayKeyId';
$payment_upi_id = $settings['payment_upi_id'] ?? 'payment@upi';
$institute_name = $settings['institute_name'] ?? 'Institute';
$payment_qr_image = $settings['payment_qr_image'] ?? 'assets/img/payment-qr-default.png';
// Handle the payment form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit_payment'])) {
// Get form data
$student_id = $_SESSION['user_id'];
$course_id = $_POST['course_id'] ?? 0;
$amount = $_POST['amount'] ?? 0;
$payment_method = $_POST['payment_method'] ?? '';
$transaction_id = $_POST['transaction_id'] ?? '';
$payment_details = $_POST['payment_for'] ?? '';
$payment_type = $_POST['payment_type'] ?? 'course_fee'; // Default to course fee
$cert_id = $_POST['cert_id'] ?? 0; // For certificate payments
// Validation
if (empty($course_id) || empty($amount) || empty($payment_method)) {
$error_message = "Please fill in all required fields.";
} else{
// If no errors, process the payment
if (empty($error_message)) {
if ($payment_method === 'razorpay') {
// Redirect to appropriate payment process based on payment type
if ($payment_type === 'certificate_fee' && $cert_id > 0) {
header("Location: certificate_payment.php?course_id=$course_id&amount=$amount&cert_id=$cert_id");
exit();
} else {
header("Location: certificate_payment.php?course_id=$course_id&amount=$amount&payment_for=" . urlencode($payment_details));
exit();
}
} else {
// Manual payment process
// Get enrollment ID if this is a course payment
if ($payment_type === 'course_fee') {
$enrollment_query = "SELECT id FROM enrollments WHERE user_id = ? AND course_id = ?";
$stmt = $conn->prepare($enrollment_query);
$stmt->bind_param("ii", $student_id, $course_id);
$stmt->execute();
$enrollment_result = $stmt->get_result();
if ($enrollment_result->num_rows === 0) {
$error_message = "Enrollment not found.";
} else {
$enrollment_id = $enrollment_result->fetch_assoc()['id'];
}
}
if (empty($error_message)) {
// Insert payment record
$insert_query = "
INSERT INTO payments (
user_id, course_id, amount, payment_method,
transaction_id, status
) VALUES (?, ?, ?, ?, ?, 'pending')
";
$stmt = $conn->prepare($insert_query);
$stmt->bind_param("iidss", $student_id, $course_id, $amount,
$payment_method, $transaction_id);
if ($stmt->execute()) {
$payment_id = $conn->insert_id;
// If this is a certificate payment, update certificate status
if ($payment_type === 'certificate_fee' && $cert_id > 0) {
$update_cert = "UPDATE unified_certificates
SET payment_status = 'verification_pending', payment_date = NOW(),
payment_reference = ?
WHERE id = ? AND user_id = ?";
$cert_stmt = $conn->prepare($update_cert);
$cert_stmt->bind_param("sii", $transaction_id, $cert_id, $student_id);
$cert_stmt->execute();
$success_message = "Certificate payment submitted successfully and is pending verification.";
} else {
$success_message = "Payment submitted successfully and is pending verification.";
}
} else {
$error_message = "Error submitting payment: " . $stmt->error;
}
}
}
}
}
}
// Get all enrollments for the student
$enrollments_query = "
SELECT e.id, e.course_id, e.enrollment_date, e.status, e.payment_plan,
c.title as course_title, c.price, c.discount_price, c.image as course_image, c.duration,
(
SELECT SUM(amount)
FROM payments
WHERE user_id = ? AND course_id = e.course_id AND status IN ('completed', 'verified')
) as course_paid
FROM enrollments e
INNER JOIN courses c ON e.course_id = c.id
WHERE e.user_id = ? AND e.status != 'cancelled'
ORDER BY e.enrollment_date DESC
";
$stmt = $conn->prepare($enrollments_query);
$stmt->bind_param("ii", $student_id, $student_id);
$stmt->execute();
$enrollments_result = $stmt->get_result();
$enrollments = [];
$upcoming_payments = [];
$total_paid = 0;
$total_amount = 0;
// Process each enrollment to calculate payment details
while ($enrollment = $enrollments_result->fetch_assoc()) {
// Calculate course price (considering discount if available)
$course_price = $enrollment['discount_price'] > 0 && $enrollment['discount_price'] < $enrollment['price']
? $enrollment['discount_price'] : $enrollment['price'];
// Parse course duration to determine payment schedule
$duration_parts = explode(' ', $enrollment['duration']);
$duration_value = isset($duration_parts[0]) ? intval($duration_parts[0]) : 3; // Default to 3 if not specified
$duration_unit = isset($duration_parts[1]) ? strtolower($duration_parts[1]) : 'months'; // Default to months
// Normalize duration to months for calculation
$duration_in_months = $duration_value;
if ($duration_unit === 'days') {
$duration_in_months = max(1, ceil($duration_value / 30)); // Convert days to months (minimum 1 month)
} else if ($duration_unit === 'weeks') {
$duration_in_months = max(1, ceil($duration_value / 4)); // Convert weeks to months (minimum 1 month)
} else if ($duration_unit === 'years') {
$duration_in_months = $duration_value * 12; // Convert years to months
}
// Calculate payment plans based on course duration
$monthly_price = round($course_price / $duration_in_months); // Monthly payment (total divided by course duration in months)
$half_duration_months = max(1, ceil($duration_in_months / 2)); // Half the course duration (minimum 1 month)
$half_duration_price = round($course_price / $half_duration_months); // Price for half-duration plan
// Maximum number of installments shouldn't exceed the course duration
$max_installments = min(12, $duration_in_months);
$installment_price = $monthly_price;
if ($max_installments < 1) {
$max_installments = 1;
$installment_price = $course_price;
}
// Set payment plan details based on the enrollment payment plan
if ($enrollment['payment_plan'] === 'monthly') {
$enrollment['payment_type'] = 'Monthly';
$enrollment['payments_count'] = $duration_in_months;
$enrollment['fee_amount'] = $monthly_price; // Monthly installment
$payment_frequency = 1; // 1 month interval
} else if ($enrollment['payment_plan'] === 'half_duration') {
// For half-duration plans
$enrollment['payment_type'] = 'Half Duration';
$enrollment['payments_count'] = $half_duration_months;
$enrollment['fee_amount'] = $half_duration_price;
$payment_frequency = ceil($duration_in_months / $half_duration_months); // Half duration interval
} else if ($enrollment['payment_plan'] === 'six_month') {
// For 6-month plans
$enrollment['payment_type'] = 'Six Month Plan';
$enrollment['payments_count'] = max(1, ceil($duration_in_months / 6));
$enrollment['fee_amount'] = round($course_price / $enrollment['payments_count']);
$payment_frequency = 6; // 6 month interval
} else {
// Full payment
$enrollment['payment_type'] = 'Full Payment';
$enrollment['payments_count'] = 1;
$enrollment['fee_amount'] = $course_price;
$payment_frequency = 0; // One-time payment
}
// Set total fee
$enrollment['total_fee'] = $course_price;
$enrollment['course_paid'] = $enrollment['course_paid'] ?? 0;
$enrollment['remaining_amount'] = max(0, $enrollment['total_fee'] - $enrollment['course_paid']);
$enrollment['payment_progress'] = $enrollment['total_fee'] > 0 ?
min(100, round(($enrollment['course_paid'] / $enrollment['total_fee']) * 100)) : 0;
// Add to totals
$total_paid += $enrollment['course_paid'];
$total_amount += $enrollment['total_fee'];
// Add to enrollments array
$enrollments[] = $enrollment;
// Calculate the next payment date and amount if there's a remaining balance
if ($enrollment['remaining_amount'] > 0 && $enrollment['status'] === 'active') {
// Calculate how many installments have been paid
$installments_paid = floor($enrollment['course_paid'] / $enrollment['fee_amount']);
$installments_remaining = $enrollment['payments_count'] - $installments_paid;
if ($installments_remaining > 0 && $enrollment['payment_plan'] !== 'full') {
// Find the last payment date
$last_payment_query = "SELECT payment_date
FROM payments
WHERE user_id = ? AND course_id = ? AND status IN ('completed', 'verified')
ORDER BY payment_date DESC
LIMIT 1";
$stmt_payment = $conn->prepare($last_payment_query);
$stmt_payment->bind_param("ii", $student_id, $enrollment['course_id']);
$stmt_payment->execute();
$payment_result = $stmt_payment->get_result();
// Calculate next payment date
if ($payment_result->num_rows > 0) {
// Use the last payment date as reference
$last_payment = $payment_result->fetch_assoc();
$next_payment_date = new DateTime($last_payment['payment_date']);
// Add appropriate interval based on payment plan
if ($enrollment['payment_plan'] === 'monthly') {
$next_payment_date->add(new DateInterval('P1M'));
} else if ($enrollment['payment_plan'] === 'half_duration') {
// For half-duration plan, add the appropriate number of months
$next_payment_date->add(new DateInterval('P' . $payment_frequency . 'M'));
} else if ($enrollment['payment_plan'] === 'six_month') {
$next_payment_date->add(new DateInterval('P6M'));
} else if ($enrollment['payment_plan'] === 'quarterly') {
$next_payment_date->add(new DateInterval('P3M'));
}
} else {
// Use enrollment date as reference if no payments yet
$next_payment_date = new DateTime($enrollment['enrollment_date']);
// For first payment, use the enrollment date directly
// No need to add interval for the first payment
}
// Only add to upcoming payments if the date is in the future
$current_date = new DateTime();
if ($next_payment_date > $current_date) {
$upcoming_payments[] = [
'course_id' => $enrollment['course_id'],
'course_title' => $enrollment['course_title'],
'course_image' => $enrollment['course_image'],
'amount' => $enrollment['fee_amount'],
'payment_date' => $next_payment_date->format('Y-m-d'),
'payment_plan' => $enrollment['payment_plan'],
'installment_number' => $installments_paid + 1,
'total_installments' => $enrollment['payments_count']
];
}
}
}
}
// Sort upcoming payments by date (earliest first)
usort($upcoming_payments, function($a, $b) {
return strtotime($a['payment_date']) - strtotime($b['payment_date']);
});
// Get payment history
$payments_query = "
SELECT p.id, p.amount, p.payment_method, p.status as payment_status,
p.transaction_id, p.payment_date, p.payment_details,
c.title as course_title
FROM payments p
INNER JOIN courses c ON p.course_id = c.id
WHERE p.user_id = ?
ORDER BY p.payment_date DESC
";
$stmt = $conn->prepare($payments_query);
$stmt->bind_param("i", $student_id);
$stmt->execute();
$payments_result = $stmt->get_result();
$payments = [];
while ($row = $payments_result->fetch_assoc()) {
$payments[] = $row;
}
// Calculate total pending amount
$total_pending = max(0, $total_amount - $total_paid);
$payment_progress = $total_amount > 0 ? min(100, round(($total_paid / $total_amount) * 100)) : 0;
// Get active enrollments with remaining balance
$active_enrollments = array_filter($enrollments, function($enrollment) {
return $enrollment['remaining_amount'] > 0 && $enrollment['status'] === 'active';
});
// Get certificate payment information for this student
$certificate_payments_query = "
SELECT uc.id as cert_id, uc.certificate_number, uc.issue_date, uc.payment_status,
c.id as course_id, c.title as course_title, c.image as course_image,
(
SELECT SUM(amount)
FROM payments
WHERE user_id = ? AND course_id = c.id AND status IN ('completed', 'verified')
) as cert_paid
FROM unified_certificates uc
INNER JOIN courses c ON uc.course_id = c.id
WHERE uc.user_id = ?
ORDER BY uc.issue_date DESC
";
$stmt = $conn->prepare($certificate_payments_query);
$stmt->bind_param("ii", $student_id, $student_id);
$stmt->execute();
$certificate_payments_result = $stmt->get_result();
$certificate_payments = [];
while ($cert_payment = $certificate_payments_result->fetch_assoc()) {
$certificate_payments[] = $cert_payment;
}
?>
<div class="container py-4">
<style>
/* Animation for highlighting the payment form */
@keyframes highlightForm {
0% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); }
20% { box-shadow: 0 0 0 10px rgba(0, 123, 255, 0.3); }
100% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); }
}
.highlight-section {
animation: highlightForm 2s ease-out;
}
/* Styling for payment form elements */
#payment-options {
transition: all 0.3s ease;
scroll-margin-top: 20px;
}
/* Style the upcoming payments table */
#upcomingPaymentsTable .btn-primary {
transition: all 0.2s ease-in-out;
}
#upcomingPaymentsTable .btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
/* Style the form inputs */
#paymentForm .form-control:focus {
border-color: #4e73df;
box-shadow: 0 0 0 0.25rem rgba(78, 115, 223, 0.25);
}
.payment-methods{
margin-left: 1rem;
}
/* Payment method styling */
.payment-methods .form-check {
padding: 0.5rem;
border-radius: 0.375rem;
transition: background-color 0.2s;
}
.payment-methods .form-check-input:checked ~ .form-check-label {
font-weight: 500;
color: #4e73df;
}
</style>
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Payment Dashboard</h1>
</div>
<?php if ($success_message): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="fas fa-check-circle me-2"></i> <?php echo $success_message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error_message): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="fas fa-exclamation-circle me-2"></i> <?php echo $error_message; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<!-- Payment Overview Cards -->
<div class="row mb-4">
<div class="col-xl-4 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 Course Fees</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-4 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 Paid</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">₹<?php echo number_format($total_paid, 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-4 col-md-6 mb-4">
<div class="card border-left-danger 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-danger text-uppercase mb-1">
Remaining Balance</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">₹<?php echo number_format($total_pending, 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>
<!-- Payment Progress -->
<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">Payment Progress</h6>
</div>
<div class="card-body">
<div class="mb-2 d-flex justify-content-between">
<div>Overall Progress</div>
<div class="text-primary"><?php echo $payment_progress; ?>% Complete</div>
</div>
<div class="progress mb-4" style="height: 15px;">
<div class="progress-bar bg-primary" role="progressbar" style="width: <?php echo $payment_progress; ?>%"
aria-valuenow="<?php echo $payment_progress; ?>" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<?php if (!empty($upcoming_payments)): ?>
<!-- Upcoming Payments -->
<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">Upcoming Payments</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="upcomingPaymentsTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Course</th>
<th>Due Date</th>
<th>Amount</th>
<th>Installment</th>
<th>Payment Plan</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($upcoming_payments as $payment): ?>
<tr>
<td>
<div class="d-flex align-items-center">
<?php if (!empty($payment['course_image'])): ?>
<img src="../<?php echo $payment['course_image']; ?>" alt="Course" class="img-thumbnail me-2" style="width: 50px; height: 50px; object-fit: cover;">
<?php endif; ?>
<div><?php echo htmlspecialchars($payment['course_title']); ?></div>
</div>
</td>
<td>
<?php
$due_date = new DateTime($payment['payment_date']);
$today = new DateTime();
$days_remaining = $today->diff($due_date)->days;
$date_class = $days_remaining <= 7 ? 'text-danger' : '';
?>
<span class="<?php echo $date_class; ?>">
<?php echo date('M d, Y', strtotime($payment['payment_date'])); ?>
<?php if ($days_remaining <= 7): ?>
<span class="badge bg-danger ms-1">Due soon</span>
<?php endif; ?>
</span>
</td>
<td>₹<?php echo number_format($payment['amount'], 2); ?></td>
<td>
<div class="d-flex align-items-center">
<span><?php echo $payment['installment_number']; ?> of <?php echo $payment['total_installments']; ?></span>
<div class="progress ms-2" style="width: 60px; height: 6px;">
<div class="progress-bar" role="progressbar"
style="width: <?php echo ($payment['installment_number'] / $payment['total_installments']) * 100; ?>%"
aria-valuenow="<?php echo ($payment['installment_number'] / $payment['total_installments']) * 100; ?>"
aria-valuemin="0"
aria-valuemax="100"></div>
</div>
</div>
</td>
<td>
<?php
$plan_label = 'Full Payment';
if ($payment['payment_plan'] === 'monthly') {
$plan_label = 'Monthly';
} else if ($payment['payment_plan'] === 'half_duration') {
$plan_label = 'Half Duration';
} else if ($payment['payment_plan'] === 'six_month') {
$plan_label = 'Six Month Plan';
} else if ($payment['payment_plan'] === 'full') {
$plan_label = 'Full Payment';
}
echo $plan_label;
?>
</td>
<td>
<a href="#payment-options" class="btn btn-sm btn-primary"
onclick="setPaymentCourse(<?php echo $payment['course_id']; ?>, <?php echo floatval($payment['amount']); ?>, <?php
// Find the enrollment for this course
$enrollment_remaining = 0;
foreach ($active_enrollments as $enroll) {
if ($enroll['course_id'] == $payment['course_id']) {
$enrollment_remaining = floatval($enroll['remaining_amount']);
break;
}
}
echo $enrollment_remaining;
?>)"
data-bs-toggle="tooltip"
title="Pay ₹<?php echo number_format($payment['amount'], 2); ?> for <?php echo htmlspecialchars($payment['course_title']); ?>">
<i class="fas fa-credit-card me-1"></i> Pay Now
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if (count($upcoming_payments) > 5): ?>
<div class="text-center mt-3">
<a href="payment_schedule.php" class="btn btn-outline-primary btn-sm">
<i class="fas fa-calendar-alt me-1"></i> View Full Payment Schedule
</a>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if (!empty($active_enrollments)): ?>
<!-- Payment Options -->
<div id="payment-options" class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Make Payment</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-7">
<form id="paymentForm" method="POST" action="" enctype="multipart/form-data" class="mb-4">
<div class="mb-3">
<label for="course_id" class="form-label">Select Course <span class="text-danger">*</span></label>
<select class="form-control" id="course_id" name="course_id" required>
<option value="">-- Select Course --</option>
<?php foreach ($active_enrollments as $enrollment): ?>
<option value="<?php echo $enrollment['course_id']; ?>"
data-fee="<?php echo $enrollment['remaining_amount']; ?>"
data-title="<?php echo htmlspecialchars($enrollment['course_title']); ?>">
<?php echo htmlspecialchars($enrollment['course_title']); ?> (₹<?php echo number_format($enrollment['remaining_amount'], 2); ?> remaining)
</option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Amount (₹) <span class="text-danger">*</span></label>
<input type="number" class="form-control" id="amount" name="amount" step="0.01" min="1" required>
<div class="form-text">Enter payment amount (Max: <span id="max-amount">0.00</span>)</div>
</div>
<div class="mb-3">
<label for="payment_for" class="form-label">Payment Purpose</label>
<input type="text" class="form-control" id="payment_for" name="payment_for" placeholder="e.g., Course Fee, Monthly Installment, etc.">
</div>
<div class="mb-3">
<label class="form-label">Payment Method <span class="text-danger">*</span></label>
<div class="payment-methods">
<div class="form-check mb-2">
<input class="form-check-input" type="radio" name="payment_method" id="method-razorpay" value="razorpay" checked>
<label class="form-check-label" for="method-razorpay">
<img src="../assets/img/razorpay-logo.svg" alt="" height="20" class="me-2">
Pay Online (Credit/Debit Card, UPI, Netbanking)
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="payment_method" id="method-cash" value="cash">
<label class="form-check-label" for="method-cash">
<i class="fas fa-money-bill-wave me-2"></i>
Cash Payment
</label>
</div>
</div>
</div>
<!-- Cash Payment Details (hidden by default) -->
<div id="cash-details" class="payment-details mb-3" style="display: none;">
<div class="card">
<div class="card-body bg-light">
<h6 class="card-title">Cash Payment Instructions</h6>
<div class="alert alert-warning mb-3">
<i class="fas fa-info-circle me-2"></i> Cash payments must be made in person at the institute's office during business hours.
</div>
<p class="mb-1"><strong>Payment Location:</strong> <?php echo $institute_name; ?> Main Office</p>
<p class="mb-1"><strong>Office Hours:</strong> Monday to Saturday, 9:00 AM to 5:00 PM</p>
<p class="mb-1"><strong>Amount to Pay:</strong> ₹<span id="cash-amount">0.00</span></p>
<p class="mb-3"><small class="text-muted">Please bring the exact amount if possible. Collect your receipt after payment.</small></p>
<div class="form-check mt-3">
<input class="form-check-input" type="checkbox" id="cash-confirmation" required>
<label class="form-check-label" for="cash-confirmation">
I confirm that I will make this cash payment in person.
</label>
</div>
</div>
</div>
</div>
<!-- Transaction ID for cash payments -->
<div id="transaction-id-field" class="mb-3" style="display: none;">
<label for="transaction_id" class="form-label">Receipt Number <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="transaction_id" name="transaction_id">
<div class="form-text">If you already made the payment, enter the receipt number. Otherwise, leave blank and you'll receive it after payment.</div>
</div>
<div class="d-grid gap-2">
<button type="submit" name="submit_payment" class="btn btn-primary btn-lg">
<i class="fas fa-check-circle me-2"></i> Submit Payment
</button>
</div>
</form>
</div>
<div class="col-md-5">
<div class="card h-100">
<div class="card-header">
<h6 class="m-0 font-weight-bold text-primary">Course Payment Summary</h6>
</div>
<div class="card-body">
<div id="payment-summary" class="mb-4">
<p class="text-center text-muted mb-4">Select a course to view payment summary</p>
<div id="payment-details" style="display:none;">
<div class="mb-3">
<h5 class="course-title mb-2"></h5>
<div class="progress" style="height: 8px;">
<div class="progress-bar payment-progress" role="progressbar" style="width: 0%"></div>
</div>
<div class="d-flex justify-content-between mt-1">
<small class="text-muted payment-percent">0% paid</small>
<small class="text-muted payment-amount">₹0 / ₹0</small>
</div>
</div>
<table class="table table-sm">
<tr>
<td>Total Fee:</td>
<td class="text-end course-fee">₹0.00</td>
</tr>
<tr>
<td>Amount Paid:</td>
<td class="text-end course-paid">₹0.00</td>
</tr>
<tr class="table-active">
<td><strong>Remaining:</strong></td>
<td class="text-end text-danger course-remaining"><strong>₹0.00</strong></td>
</tr>
</table>
</div>
</div>
<div class="alert alert-info">
<h6 class="alert-heading"><i class="fas fa-info-circle me-2"></i> Payment Information</h6>
<ul class="mb-0 ps-3 small">
<li>Payments are verified within 24-48 hours</li>
<li>For online payments, validation is automatic</li>
<li>Keep proof of payment for verification</li>
<li>Contact administration for payment issues</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>
<!-- Payment History -->
<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">Payment History</h6>
<a href="payment_history.php" class="btn btn-sm btn-primary">
<i class="fas fa-history me-1"></i> View All
</a>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-hover" id="paymentHistoryTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Date</th>
<th>Course</th>
<th>Amount</th>
<th>Method</th>
<th>Status</th>
<th>Reference</th>
</tr>
</thead>
<tbody>
<?php
// Re-prepare and execute the query for payment history display
$stmt = $conn->prepare($payments_query);
$stmt->bind_param("i", $student_id);
$stmt->execute();
$payments_result = $stmt->get_result();
$count = 0;
while ($payment = $payments_result->fetch_assoc() and $count < 5):
$count++;
// Ensure payment date is valid before formatting
$payment_date = 'N/A';
if (!empty($payment['payment_date']) && $payment['payment_date'] !== null) {
try {
$payment_date = date('M d, Y', strtotime($payment['payment_date']));
} catch (Exception $e) {
// Keep the default 'N/A' if date parsing fails
}
}
?>
<tr>
<td><?php echo $payment_date; ?></td>
<td><?php echo htmlspecialchars($payment['course_title'] ?? 'Unknown Course'); ?></td>
<td>₹<?php echo number_format($payment['amount'] ?? 0, 2); ?></td>
<td>
<?php
$payment_method = $payment['payment_method'] ?? '';
$method_label = $payment_method ? ucfirst($payment_method) : 'Unknown';
$method_icon = 'credit-card';
if ($payment_method === 'razorpay') {
$method_icon = 'credit-card';
$method_label = 'Online';
} elseif ($payment_method === 'upi') {
$method_icon = 'mobile-alt';
$method_label = 'UPI';
} elseif ($payment_method === 'manual') {
$method_icon = 'university';
$method_label = 'Bank';
} elseif ($payment_method === 'cash') {
$method_icon = 'money-bill-wave';
$method_label = 'Cash';
}
?>
<span><i class="fas fa-<?php echo $method_icon; ?> me-1"></i> <?php echo $method_label; ?></span>
</td>
<td>
<span class="badge bg-<?php
$payment_status = $payment['payment_status'] ?? '';
echo ($payment_status === 'completed' || $payment_status === 'verified') ? 'success' :
($payment_status === 'pending' ? 'warning' :
($payment_status === 'rejected' ? 'danger' : 'secondary'));
?>">
<?php echo ucfirst($payment['payment_status'] ?? 'Unknown'); ?>
</span>
</td>
<td><?php echo !empty($payment['transaction_id']) ? $payment['transaction_id'] : '-'; ?></td>
</tr>
<?php endwhile; ?>
<?php if ($count === 0): ?>
<tr>
<td colspan="6" class="text-center">No payment records found.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<!-- Certificate Payments Section -->
<?php if (!empty($certificate_payments)): ?>
<div class="card mb-4">
<div class="card-header bg-primary text-white">
<div class="d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="fas fa-certificate me-2"></i>Certificate Payments</h5>
<a href="certificates.php" class="btn btn-sm btn-light">View All Certificates</a>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Course</th>
<th>Certificate Number</th>
<th>Issue Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php foreach ($certificate_payments as $cert): ?>
<tr>
<td><?php echo htmlspecialchars($cert['course_title']); ?></td>
<td><?php echo htmlspecialchars($cert['certificate_number']); ?></td>
<td><?php echo date('d M Y', strtotime($cert['issue_date'])); ?></td>
<td>
<?php if ($cert['payment_status'] === 'completed' || $cert['payment_status'] === 'paid'): ?>
<span class="badge bg-success">Paid</span>
<?php elseif ($cert['payment_status'] === 'verification_pending'): ?>
<span class="badge bg-warning">Pending Verification</span>
<?php else: ?>
<span class="badge bg-danger">Payment Required</span>
<?php endif; ?>
</td>
<td>
<?php if ($cert['payment_status'] === 'completed' || $cert['payment_status'] === 'paid'): ?>
<a href="view_certificate.php?cert_id=<?php echo $cert['cert_id']; ?>" class="btn btn-primary btn-sm">
<i class="fas fa-download me-1"></i> View Certificate
</a>
<?php elseif ($cert['payment_status'] === 'verification_pending'): ?>
<span class="text-muted">Awaiting verification</span>
<?php else: ?>
<a href="certificate_payment.php?course_id=<?php echo $cert['course_id']; ?>&cert_id=<?php echo $cert['cert_id']; ?>&amount=700" class="btn btn-warning btn-sm">
<i class="fas fa-credit-card me-1"></i> Pay Now
</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Payment method selection
const paymentMethodRadios = document.querySelectorAll('input[name="payment_method"]');
const cashDetails = document.getElementById('cash-details');
const transactionIdField = document.getElementById('transaction-id-field');
const courseSelect = document.getElementById('course_id');
const amountInput = document.getElementById('amount');
const maxAmountSpan = document.getElementById('max-amount');
const cashAmountSpan = document.getElementById('cash-amount');
paymentMethodRadios.forEach(radio => {
radio.addEventListener('change', function() {
// Hide all payment details first
cashDetails.style.display = 'none';
transactionIdField.style.display = 'none';
// Show relevant details based on selected payment method
if (this.value === 'cash') {
cashDetails.style.display = 'block';
transactionIdField.style.display = 'block';
}
});
});
// Course selection
courseSelect.addEventListener('change', function() {
if (this.value) {
const selectedOption = this.options[this.selectedIndex];
const maxFee = parseFloat(selectedOption.dataset.fee);
const courseId = parseInt(this.value);
// Update max amount (always shows the total remaining amount)
maxAmountSpan.textContent = maxFee.toFixed(2);
// Find installment amount if available
let installmentAmount = maxFee;
const upcomingPaymentsTable = document.getElementById('upcomingPaymentsTable');
if (upcomingPaymentsTable) {
const rows = upcomingPaymentsTable.querySelectorAll('tbody tr');
for (const row of rows) {
const courseLink = row.querySelector('a[onclick]');
if (courseLink && courseLink.getAttribute('onclick').includes(`setPaymentCourse(${courseId}`)) {
// Extract the amount from the payment row
const amountText = row.cells[2].textContent.replace(/[^0-9.]/g, '');
installmentAmount = parseFloat(amountText) || maxFee;
break;
}
}
}
// Set cash amount to installment amount
cashAmountSpan.textContent = installmentAmount.toFixed(2);
// Set default amount to installment amount (not the max remaining)
amountInput.value = installmentAmount.toFixed(2);
// The maximum allowed is still the full remaining amount
amountInput.max = maxFee;
// Load course payment details
loadCoursePaymentDetails(this.value);
} else {
document.getElementById('payment-details').style.display = 'none';
}
});
// Initialize payment status chart if the element exists
const chartElement = document.getElementById('paymentStatusChart');
if (chartElement) {
const ctx = chartElement.getContext('2d');
const paymentStatusChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Paid', 'Remaining'],
datasets: [{
data: [<?php echo $total_paid; ?>, <?php echo $total_pending; ?>],
backgroundColor: ['#1cc88a', '#e74a3b'],
hoverBackgroundColor: ['#17a673', '#e02d1b'],
hoverBorderColor: "rgba(234, 236, 244, 1)",
}]
},
options: {
maintainAspectRatio: false,
cutout: '70%',
plugins: {
legend: {
display: true,
position: 'bottom'
}
}
}
});
}
// Form validation
const paymentForm = document.getElementById('paymentForm');
paymentForm.addEventListener('submit', function(e) {
const courseId = courseSelect.value;
const amount = parseFloat(amountInput.value);
const paymentMethod = document.querySelector('input[name="payment_method"]:checked').value;
if (!courseId) {
e.preventDefault();
alert('Please select a course.');
return;
}
if (isNaN(amount) || amount <= 0) {
e.preventDefault();
alert('Please enter a valid payment amount.');
return;
}
const maxAmount = parseFloat(maxAmountSpan.textContent);
if (amount > maxAmount) {
e.preventDefault();
alert(`Payment amount cannot exceed ₹${maxAmount.toFixed(2)}.`);
return;
}
if (paymentMethod === 'cash') {
// Check if cash confirmation is checked
const cashConfirmation = document.getElementById('cash-confirmation');
if (cashConfirmation && !cashConfirmation.checked) {
e.preventDefault();
alert('Please confirm that you will make the cash payment in person.');
return;
}
// Transaction ID is optional for cash payments
const transactionId = document.getElementById('transaction_id').value;
if (transactionId) {
// If transaction ID is provided, validate its format
if (transactionId.length < 3) {
e.preventDefault();
alert('Receipt number should be at least 3 characters long.');
return;
}
}
}
});
});
function setPaymentCourse(courseId, amount, remainingAmount) {
console.log(`Setting course: ${courseId} with amount: ${amount}, remaining: ${remainingAmount}`);
// Set the selected course in the payment form
const courseSelect = document.getElementById('course_id');
if (!courseSelect) {
console.error('Course select element not found');
return;
}
// Find and select the matching course option
let found = false;
let courseTitle = '';
for (let i = 0; i < courseSelect.options.length; i++) {
if (courseSelect.options[i].value == courseId) {
courseSelect.selectedIndex = i;
courseTitle = courseSelect.options[i].dataset.title || '';
// Ensure the option has the correct remaining amount data attribute
courseSelect.options[i].dataset.fee = remainingAmount.toFixed(2);
found = true;
console.log(`Selected course at index ${i}: ${courseTitle}`);
break;
}
}
if (!found) {
console.error(`Course ID ${courseId} not found in options`);
return;
}
// Set the amount field to the INSTALLMENT amount (not the full remaining amount)
const amountInput = document.getElementById('amount');
if (amountInput) {
amountInput.value = amount.toFixed(2);
// The maximum is still the full remaining amount
amountInput.max = remainingAmount;
console.log(`Set amount to ${amount.toFixed(2)}, max: ${remainingAmount}`);
}
// Set a meaningful payment purpose based on course title
const paymentPurpose = document.getElementById('payment_for');
if (paymentPurpose) {
const currentDate = new Date();
const month = currentDate.toLocaleString('default', { month: 'long' });
const year = currentDate.getFullYear();
// Get the installment number if available
const upcomingPaymentsTable = document.getElementById('upcomingPaymentsTable');
let installmentInfo = '';
if (upcomingPaymentsTable) {
const rows = upcomingPaymentsTable.querySelectorAll('tbody tr');
for (const row of rows) {
const courseCellContent = row.cells[0].textContent;
const installmentCell = row.cells[3].textContent;
if (courseCellContent.includes(courseTitle)) {
installmentInfo = installmentCell.trim();
break;
}
}
}
// Create a descriptive payment purpose
if (installmentInfo) {
paymentPurpose.value = `${courseTitle} - Installment ${installmentInfo} (${month} ${year})`;
} else {
paymentPurpose.value = `${courseTitle} - Course Fee Payment (${month} ${year})`;
}
console.log(`Set payment purpose: ${paymentPurpose.value}`);
}
// Update amount displays:
// - maxAmountSpan shows the FULL remaining amount (maximum that can be paid)
// - cashAmountSpan shows the INSTALLMENT amount (suggested payment)
const maxAmountSpan = document.getElementById('max-amount');
const cashAmountSpan = document.getElementById('cash-amount');
if (maxAmountSpan) maxAmountSpan.textContent = remainingAmount.toFixed(2);
if (cashAmountSpan) cashAmountSpan.textContent = amount.toFixed(2);
// Load course payment details immediately
loadCoursePaymentDetails(courseId);
// Scroll to payment options
const paymentOptions = document.getElementById('payment-options');
if (paymentOptions) {
paymentOptions.scrollIntoView({
behavior: 'smooth'
});
}
// DON'T trigger the change event as it would reset our carefully set values
// We've already done everything the change event would do
// Add highlight animation to the payment form
const paymentForm = document.getElementById('paymentForm');
if (paymentForm) {
paymentForm.classList.add('highlight-section');
setTimeout(() => {
paymentForm.classList.remove('highlight-section');
}, 2000);
// Focus on the first field after scrolling
setTimeout(() => {
courseSelect.focus();
}, 600);
}
}
// Function to load course payment details
function loadCoursePaymentDetails(courseId) {
if (!courseId) return;
// Show loading state
const paymentDetails = document.getElementById('payment-details');
const loadingMessage = document.querySelector('#payment-summary p.text-center');
if (loadingMessage) {
loadingMessage.textContent = 'Loading payment details...';
}
// Get course details (asynchronously)
fetch(`ajax/get_course_payment_details.php?course_id=${courseId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
// Hide loading message if exists
if (loadingMessage) {
loadingMessage.style.display = 'none';
}
// Show payment details
if (paymentDetails) {
paymentDetails.style.display = 'block';
}
// Update UI with payment details
document.querySelector('.course-title').textContent = data.course_title;
document.querySelector('.course-fee').textContent = `₹${parseFloat(data.total_fee).toFixed(2)}`;
document.querySelector('.course-paid').textContent = `₹${parseFloat(data.paid_amount).toFixed(2)}`;
document.querySelector('.course-remaining').textContent = `₹${parseFloat(data.remaining).toFixed(2)}`;
const progressPercent = parseFloat(data.total_fee) > 0 ?
(parseFloat(data.paid_amount) / parseFloat(data.total_fee)) * 100 : 0;
document.querySelector('.payment-progress').style.width = `${progressPercent}%`;
document.querySelector('.payment-percent').textContent = `${Math.round(progressPercent)}% paid`;
document.querySelector('.payment-amount').textContent =
`₹${parseFloat(data.paid_amount).toFixed(2)} / ₹${parseFloat(data.total_fee).toFixed(2)}`;
} else {
// Show error in the payment summary
if (loadingMessage) {
loadingMessage.textContent = data.message || 'Could not load payment details';
loadingMessage.style.display = 'block';
}
if (paymentDetails) {
paymentDetails.style.display = 'none';
}
}
})
.catch(error => {
console.error('Error fetching course payment details:', error);
// Show error in the payment summary
if (loadingMessage) {
loadingMessage.textContent = 'Error loading payment details. Please try again.';
loadingMessage.style.display = 'block';
}
if (paymentDetails) {
paymentDetails.style.display = 'none';
}
});
}
// Add highlighting style
const style = document.createElement('style');
style.textContent = `
.highlight-section {
animation: highlightForm 2s ease-out;
}
@keyframes highlightForm {
0% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); }
20% { box-shadow: 0 0 0 10px rgba(0, 123, 255, 0.3); }
100% { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0); }
}
`;
document.head.appendChild(style);
// Add course selection change handler
document.addEventListener('DOMContentLoaded', function() {
const courseSelect = document.getElementById('course_id');
const amountInput = document.getElementById('amount');
const maxAmountSpan = document.getElementById('max-amount');
const cashAmountSpan = document.getElementById('cash-amount');
if (courseSelect) {
courseSelect.addEventListener('change', function() {
const selectedOption = courseSelect.options[courseSelect.selectedIndex];
if (selectedOption && selectedOption.value) {
const courseId = selectedOption.value;
const maxFee = parseFloat(selectedOption.dataset.fee || 0);
// Update max amount spans
if (maxAmountSpan) maxAmountSpan.textContent = maxFee.toFixed(2);
if (cashAmountSpan) cashAmountSpan.textContent = maxFee.toFixed(2);
// Set default amount to max fee
if (amountInput) {
amountInput.value = maxFee.toFixed(2);
amountInput.max = maxFee;
}
// Load course payment details
loadCoursePaymentDetails(courseId);
} else {
// Clear values when no course is selected
if (maxAmountSpan) maxAmountSpan.textContent = '0.00';
if (cashAmountSpan) cashAmountSpan.textContent = '0.00';
if (amountInput) {
amountInput.value = '';
amountInput.max = '';
}
// Hide payment details
const paymentDetails = document.getElementById('payment-details');
if (paymentDetails) {
paymentDetails.style.display = 'none';
}
// Show default message
const loadingMessage = document.querySelector('#payment-summary p.text-center');
if (loadingMessage) {
loadingMessage.textContent = 'Select a course to view payment summary';
loadingMessage.style.display = 'block';
}
}
});
}
});
// Check URL parameters for pre-filling the form (for direct navigation to payment page)
document.addEventListener('DOMContentLoaded', function() {
// Get URL parameters
const urlParams = new URLSearchParams(window.location.search);
const courseId = urlParams.get('course_id');
const amount = urlParams.get('amount');
// If parameters exist, pre-fill the form
if (courseId && amount) {
// Find the remaining amount for this course
let remainingAmount = 0;
const courseSelect = document.getElementById('course_id');
if (courseSelect) {
for (let i = 0; i < courseSelect.options.length; i++) {
if (courseSelect.options[i].value == courseId) {
remainingAmount = parseFloat(courseSelect.options[i].dataset.fee || 0);
break;
}
}
// Set the course and amounts using our function
setPaymentCourse(courseId, parseFloat(amount), remainingAmount);
}
}
});
</script>
<?php include_once 'includes/footer.php'; ?>