Merge branch 'feature/pop_submit'

This commit is contained in:
2025-06-13 10:30:27 +02:00
10 changed files with 389 additions and 1069 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
.env .env
/vendor/ /vendor/
.htaccess
/uploads/pop/

View File

@@ -197,6 +197,10 @@ if (!empty($bannerImages)) {
if (($row['status']) == 'AWAITING PAYMENT') { if (($row['status']) == 'AWAITING PAYMENT') {
echo "<td><a href='process_eft.php?token=" . encryptData($row['eft_id'], $salt) . "' class='theme-btn style-two style-three'> echo "<td><a href='process_eft.php?token=" . encryptData($row['eft_id'], $salt) . "' class='theme-btn style-two style-three'>
<span data-hover='PAYMENT RECEIVED'>" . htmlspecialchars($row['status']) . "</span> <span data-hover='PAYMENT RECEIVED'>" . htmlspecialchars($row['status']) . "</span>
</a></td></tr>";
} elseif (($row['status']) == 'PROCESSING') {
echo "<td><a href='process_payments.php' class='theme-btn style-two style-three'>
<span data-hover='PROCESS'>PROCESS</span>
</a></td></tr>"; </a></td></tr>";
} else { } else {
echo "<td>" . htmlspecialchars($row['status']) . "</td>"; echo "<td>" . htmlspecialchars($row['status']) . "</td>";

View File

@@ -236,7 +236,7 @@ function sendAdminNotification($subject, $message)
{ {
global $mailjet; global $mailjet;
$message = [ $mail = [
'Messages' => [ 'Messages' => [
[ [
'From' => [ 'From' => [
@@ -265,7 +265,7 @@ function sendAdminNotification($subject, $message)
]); ]);
$response = $client->request('POST', 'send', [ $response = $client->request('POST', 'send', [
'json' => $message, 'json' => $mail,
'auth' => ['1a44f8d5e847537dbb8d3c76fe73a93c', 'ec98b45c53a7694c4f30d09eee9ad280'] 'auth' => ['1a44f8d5e847537dbb8d3c76fe73a93c', 'ec98b45c53a7694c4f30d09eee9ad280']
]); ]);

View File

@@ -210,6 +210,7 @@ logVisitor();
<!-- <li><a href="admin_camp_bookings.php">Camping Bookings</a></li> --> <!-- <li><a href="admin_camp_bookings.php">Camping Bookings</a></li> -->
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> --> <!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
<li><a href="admin_efts.php">EFT Payments</a></li> <li><a href="admin_efts.php">EFT Payments</a></li>
<li><a href="process_payments.php">Process Payments</a></li>
<!-- <li><a href="bar_tabs.php">Bar</a></li> --> <!-- <li><a href="bar_tabs.php">Bar</a></li> -->
<?php if ($role === 'superadmin') { ?> <?php if ($role === 'superadmin') { ?>
<li><a href="admin_visitors.php">Visitor Log</a></li> <li><a href="admin_visitors.php">Visitor Log</a></li>
@@ -231,6 +232,7 @@ logVisitor();
<li><a href="account_settings.php">Account Settings</a></li> <li><a href="account_settings.php">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li> <li><a href="membership_details.php">Membership</a></li>
<li><a href="bookings.php">My Bookings</a></li> <li><a href="bookings.php">My Bookings</a></li>
<li><a href="submit_pop.php">Submit P.O.P</a></li>
<li><a href="logout.php">Log Out</a></li> <li><a href="logout.php">Log Out</a></li>
</ul> </ul>

View File

@@ -223,6 +223,7 @@ logVisitor();
<!-- <li><a href="admin_camp_bookings.php">Camping Bookings</a></li> --> <!-- <li><a href="admin_camp_bookings.php">Camping Bookings</a></li> -->
<!-- <li><a href="admin_payments.php">Payfast Payments</a></li> --> <!-- <li><a href="admin_payments.php">Payfast Payments</a></li> -->
<li><a href="admin_efts.php">EFT Payments</a></li> <li><a href="admin_efts.php">EFT Payments</a></li>
<li><a href="process_payments.php">Process Payments</a></li>
<?php if ($role === 'superadmin') { ?> <?php if ($role === 'superadmin') { ?>
<li><a href="admin_visitors.php">Visitor Log</a></li> <li><a href="admin_visitors.php">Visitor Log</a></li>
<?php } ?> <?php } ?>
@@ -237,6 +238,7 @@ logVisitor();
<li><a href="account_settings.php">Account Settings</a></li> <li><a href="account_settings.php">Account Settings</a></li>
<li><a href="membership_details.php">Membership</a></li> <li><a href="membership_details.php">Membership</a></li>
<li><a href="bookings.php">My Bookings</a></li> <li><a href="bookings.php">My Bookings</a></li>
<li><a href="submit_pop.php">Submit P.O.P</a></li>
<li><a href="logout.php">Log Out</a></li> <li><a href="logout.php">Log Out</a></li>
</ul> </ul>

View File

@@ -105,9 +105,13 @@ if (!empty($bannerImages)) {
<?php echo <?php echo
'<h5>Membership Start Date: ' . $membership_start_date . '<br>Membership Renewal Date: ' . $membership_end_date . '</h5>'; ?> '<h5>Membership Start Date: ' . $membership_start_date . '<br>Membership Renewal Date: ' . $membership_end_date . '</h5>'; ?>
</div> </div>
<p>Your invoice has been sent to <b><?php echo htmlspecialchars($user_email); ?></b>. Please send your proof of payment to <b>info@4wdcsa.co.za</b>.</p> <p>Your invoice has been sent to <b><?php echo htmlspecialchars($user_email); ?></b>. Please upload your proof of payment below.</p>
<h5>Payment Details:</h5> <h5>Payment Details:</h5>
<p>The Four Wheel Drive Club of Southern Africa<br>FNB<br>Account Number: 58810022334<br>Branch code: 250655<br>Reference: <?php echo htmlspecialchars($eft_id); ?><br>Amount: R <?php echo number_format($payment_amount, 2); ?></p> <p>The Four Wheel Drive Club of Southern Africa<br>FNB<br>Account Number: 58810022334<br>Branch code: 250655<br>Reference: <?php echo htmlspecialchars($eft_id); ?><br>Amount: R <?php echo number_format($payment_amount, 2); ?></p>
<a href="submit_pop.php" class="theme-btn style-two style-three" style="width:100%;">
<span data-hover="Submit Proof of Payment">Submit Proof of Payment</span>
<i class="fal fa-arrow-right"></i>
</a>
</div> </div>
<div class="col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50"> <div class="col-lg-6" data-aos="fade-right" data-aos-duration="1500" data-aos-offset="50">

View File

@@ -131,10 +131,14 @@ if (!empty($bannerImages)) {
</div> </div>
<p>Your invoice has been sent to <b><?php echo htmlspecialchars($user_email); ?></b>. Please send your proof of payment to <b>info@4wdcsa.co.za</b>.</p> <p>Your invoice has been sent to <b><?php echo htmlspecialchars($user_email); ?></b>. Please upload your proof of payment below.</p>
<p>Bookings not paid for within 24 hours will be forfeited.</p> <p>Bookings not paid for within 24 hours will be forfeited.</p>
<h5>Payment Details:</h5> <h5>Payment Details:</h5>
<p>The Four Wheel Drive Club of Southern Africa<br>FNB<br>Account Number: 58810022334<br>Branch code: 250655<br>Reference: <?php echo htmlspecialchars($eft_id); ?><br>Amount: R <?php echo number_format($payment_amount, 2); ?></p> <p>The Four Wheel Drive Club of Southern Africa<br>FNB<br>Account Number: 58810022334<br>Branch code: 250655<br>Reference: <?php echo htmlspecialchars($eft_id); ?><br>Amount: R <?php echo number_format($payment_amount, 2); ?></p>
<a href="submit_pop.php" class="theme-btn style-two style-three" style="width:100%;">
<span data-hover="Submit Proof of Payment">Submit Proof of Payment</span>
<i class="fal fa-arrow-right"></i>
</a>
</div> </div>
</div> </div>
</div> </div>

148
process_payments.php Normal file
View File

@@ -0,0 +1,148 @@
<?php include_once('header02.php');
checkAdmin();
checkUserSession();
$user_id = $_SESSION['user_id'];
?>
<style>
.image {
width: 400px;
/* Set your desired width */
height: 350px;
/* Set your desired height */
overflow: hidden;
/* Hide any overflow */
display: block;
/* Ensure proper block behavior */
}
.image img {
width: 100%;
/* Image scales to fill the container */
height: 100%;
/* Image scales to fill the container */
object-fit: cover;
/* Fills the container while maintaining aspect ratio */
object-position: top;
/* Aligns the top of the image with the top of the container */
display: block;
/* Prevents inline whitespace issues */
}
.message-box {
text-align: center;
position: relative;
padding: 10px;
padding-right: 35px;
/* Ensures text doesn't overlap with the close button */
}
.close-btn {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
/* Centers vertically */
cursor: pointer;
font-size: 20px;
font-weight: bold;
color: #333;
background: none;
border: none;
}
.close-btn:hover {
color: red;
}
</style>
</style>
<?php
$status = "PROCESSING";
$bannerFolder = 'assets/images/banners/';
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
if (!empty($bannerImages)) {
$randomBanner = $bannerImages[array_rand($bannerImages)];
}
?>
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="banner-overlay"></div>
<div class="container">
<div class="banner-inner text-white mb-50">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Process Payments</h2>
<nav aria-label="breadcrumb">
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
<li class="breadcrumb-item active">Process Payments</li>
</ol>
</nav>
</div>
</div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-100 rel z-1">
<div class="container">
<div class="row">
<div class="col-lg-12">
<?php if (isset($_SESSION['message'])): ?>
<div class="alert alert-warning message-box">
<?php echo $_SESSION['message']; ?>
<span class="close-btn" onclick="this.parentElement.style.display='none'">&times;</span>
</div>
<?php unset($_SESSION['message']); ?>
<?php endif; ?>
<?php
// Query to retrieve data from the bookings table
$sql = "SELECT * FROM efts WHERE status = ? ORDER BY timestamp DESC";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $status);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
// Loop through each row
while ($row = $result->fetch_assoc()) {
$eft_id = $row['eft_id'];
$eft_user = $row['user_id'];
$eft_amount = $row['amount'];
$eft_description = $row['description'];
// Output the HTML structure with dynamic data
echo '
<div class="destination-item style-three bgc-lighter booking " data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="p-4" >
<iframe src="uploads/pop/'.$eft_id.'.pdf#toolbar=0" width="400px" height="200px"></iframe>
<p><a href="uploads/pop/'.$eft_id.'.pdf" target="_new" class="theme-btn style-three" style="width:100%;">View Full PDF</a></p>
</div>
<div style="width:100%;" class="content">
<h5>' . htmlspecialchars($eft_description) . '</a></h5>
<h5>' . getFullName($eft_user) . '</a></h5>
<div class="destination-footer">
<span class="price"><span>Booking Total: R ' . number_format($eft_amount, 2) . '</span></span>
<a href="process_eft.php?token=' . encryptData($eft_id, $salt) . '" class="theme-btn style-three"><span data-hover="POP RECEIVED">PROCESS</span></a>
</div>
</div>';
}
} else {
echo '<p>There are no pending payments for processing.</p>';
}
// Close connection
$conn->close();
?>
</div>
</div>
</div>
</section>
<!-- Tour List Area end -->
<?php include_once("insta_footer.php"); ?>

219
submit_pop.php Normal file
View File

@@ -0,0 +1,219 @@
<?php include_once('header02.php');
checkUserSession();
$user_id = $_SESSION['user_id'] ?? null;
if (!$user_id) {
die("Not logged in.");
}
// Handle POST submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$eft_id = $_POST['eft_id'] ?? null;
$file_name = str_replace(' ', '_', $eft_id);
if (!$eft_id || !isset($_FILES['pop_file'])) {
echo "<div class='alert alert-danger'>Invalid submission: missing eft_id or file.</div>";
echo "<pre>";
echo "POST data: " . print_r($_POST, true);
echo "FILES data: " . print_r($_FILES, true);
echo "</pre>";
} else {
$file = $_FILES['pop_file'];
$target_dir = "uploads/pop/";
$target_file = $target_dir . $file_name . ".pdf";
// Check for upload errors first
if ($file['error'] !== UPLOAD_ERR_OK) {
echo "<div class='alert alert-danger'>Upload error code: " . $file['error'] . "</div>";
// You can decode error code if needed:
// https://www.php.net/manual/en/features.file-upload.errors.php
exit;
}
// Check for PDF extension
$file_type = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if ($file_type !== "pdf") {
echo "<div class='alert alert-danger'>Only PDF files allowed. You tried uploading: .$file_type</div>";
exit;
}
// Make sure target directory exists and writable
if (!is_dir($target_dir)) {
echo "<div class='alert alert-danger'>Upload directory does not exist: $target_dir</div>";
exit;
}
if (!is_writable($target_dir)) {
echo "<div class='alert alert-danger'>Upload directory is not writable: $target_dir</div>";
exit;
}
if (move_uploaded_file($file['tmp_name'], $target_file)) {
// Update EFT and booking status
$payment_type = $_POST['payment_type'] ?? 'booking';
if ($payment_type === 'membership') {
// Update EFT and booking status
$stmt1 = $conn->prepare("UPDATE efts SET status = 'PROCESSING' WHERE eft_id = ?");
$stmt1->bind_param("s", $eft_id);
$stmt1->execute();
// Update membership fee status
$stmt = $conn->prepare("UPDATE membership_fees SET payment_status = 'PROCESSING' WHERE payment_id = ?");
$stmt->bind_param("s", $eft_id);
$stmt->execute();
} else {
// Update EFT and booking status
$stmt1 = $conn->prepare("UPDATE efts SET status = 'PROCESSING' WHERE eft_id = ?");
$stmt1->bind_param("s", $eft_id);
$stmt1->execute();
$stmt2 = $conn->prepare("UPDATE bookings SET status = 'PROCESSING' WHERE eft_id = ?");
$stmt2->bind_param("s", $eft_id);
$stmt2->execute();
}
// Notify n8n and send the path to the uploaded file
$webhook_url = 'https://n8n.4wdcsa.co.za/webhook/process-pop';
$postData = [
'eft_id' => $eft_id,
'payment_type' => $payment_type,
];
$ch = curl_init($webhook_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
$response = curl_exec($ch);
$error = curl_error($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($error) {
error_log("Webhook Error: $error");
$_SESSION['message'] = $error;
header("Location: bookings.php");
} else {
$_SESSION['message'] = "Thank you! We are busy processing your payment!";
header("Location: bookings.php");
}
exit;
} else {
echo "<div class='alert alert-danger'>Unable to move uploaded file.</div>";
echo "<pre>Tmp file exists? " . (file_exists($file['tmp_name']) ? "Yes" : "No") . "</pre>";
echo "<pre>Tmp file path: " . htmlspecialchars($file['tmp_name']) . "</pre>";
exit;
}
}
}
// Fetch bookings for dropdown
$stmt = $conn->prepare("
SELECT eft_id AS id, 'booking' AS type FROM bookings WHERE user_id = ? AND status = 'AWAITING PAYMENT'
UNION
SELECT payment_id AS id, 'membership' AS type FROM membership_fees WHERE user_id = ? AND payment_status = 'PENDING'
");
$stmt->bind_param("ii", $user_id, $user_id);
$stmt->execute();
$result = $stmt->get_result();
$items = $result->fetch_all(MYSQLI_ASSOC);
$bannerFolder = 'assets/images/banners/';
$bannerImages = glob($bannerFolder . '*.{jpg,jpeg,png,webp}', GLOB_BRACE);
$randomBanner = 'assets/images/base4/camping.jpg'; // default fallback
if (!empty($bannerImages)) {
$randomBanner = $bannerImages[array_rand($bannerImages)];
}
?>
<section class="page-banner-area pt-50 pb-35 rel z-1 bgs-cover" style="background-image: url('<?php echo $randomBanner; ?>');">
<div class="banner-overlay"></div>
<div class="container">
<div class="banner-inner text-white mb-50">
<h2 class="page-title mb-10" data-aos="fade-left" data-aos-duration="1500" data-aos-offset="50">Submit Proof of Payment</h2>
<nav aria-label="breadcrumb">
<ol class="breadcrumb justify-content-center mb-20" data-aos="fade-right" data-aos-delay="200" data-aos-duration="1500" data-aos-offset="50">
<li class="breadcrumb-item"><a href="index.php">Home</a></li>
<li class="breadcrumb-item active">Submit Proof of Payment</li>
</ol>
</nav>
</div>
</div>
</section>
<!-- Tour List Area start -->
<section class="tour-list-page py-100 rel z-1">
<div class="container" style="max-width:600px;">
<div class="row">
<div class="comment-form bgc-lighter z-1 rel mb-30 rmb-55" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="widget widget-booking" data-aos="fade-up" data-aos-duration="1500" data-aos-offset="50">
<div class="section-title">
<h3>Submit Proof of Payment</h3>
<div style="text-align: center;" id="responseMessage"></div>
<p>To finalise your booking/membership, select the payment reference below, and then upload your PDF proof of payment.</p> <!-- Message display area -->
</div>
<?php if (count($items) > 0) {?>
<form enctype="multipart/form-data" method="POST">
<div class="row mt-35">
<ul class="tickets clearfix">
<li>
Select Payment Reference:
<select name="eft_id" id="eft_id" required onchange="updatePaymentType(this)">
<?php
if (count($items) > 0) {
foreach ($items as $item) {
$label = strtoupper($item['type']) . ' - ' . htmlspecialchars($item['id']);
echo '<option value="' . htmlspecialchars($item['id']) . '" data-type="' . $item['type'] . '">' . $label . '</option>';
}
} else {
echo '<option value="" disabled selected>No payments available</option>';
}
?>
</select>
<input type="hidden" name="payment_type" id="payment_type">
</li>
</ul>
<li>
<input style="border-radius:30px;" type="file" name="pop_file" id="pop_file" accept="application/pdf" class="form-control" required>
</li>
</div>
<div class="mt-10 mb-0">
<button type="submit" class="theme-btn style-two" style="width:100%;">Submit POP</button>
</div>
</form>
<?php
}else{
echo 'No unpaid bookings';
}?>
</div>
</div>
</div>
</div>
</section>
<script>
function updatePaymentType(selectEl) {
const selectedOption = selectEl.options[selectEl.selectedIndex];
const type = selectedOption.getAttribute('data-type');
document.getElementById('payment_type').value = type;
}
window.onload = function() {
const dropdown = document.getElementById('eft_id');
updatePaymentType(dropdown); // set default value on page load
};
</script>
<?php include_once("insta_footer.php"); ?>

File diff suppressed because it is too large Load Diff