'process_application.php']); http_response_code(403); die('Security token validation failed. Please try again.'); } // Check if user already has a membership application $check_stmt = $conn->prepare("SELECT COUNT(*) as count FROM membership_application WHERE user_id = ?"); $check_stmt->bind_param("i", $user_id); $check_stmt->execute(); $check_result = $check_stmt->get_result(); $check_row = $check_result->fetch_assoc(); $check_stmt->close(); if ($check_row['count'] > 0) { http_response_code(400); echo json_encode([ 'status' => 'error', 'message' => 'You have already submitted a membership application. Please check your email for membership details.' ]); exit; } // Check if user already has a membership fee record $fee_check_stmt = $conn->prepare("SELECT COUNT(*) as count FROM membership_fees WHERE user_id = ?"); $fee_check_stmt->bind_param("i", $user_id); $fee_check_stmt->execute(); $fee_result = $fee_check_stmt->get_result(); $fee_row = $fee_result->fetch_assoc(); $fee_check_stmt->close(); if ($fee_row['count'] > 0) { http_response_code(400); echo json_encode([ 'status' => 'error', 'message' => 'You already have a membership fee record. Please contact support if you need to update your application.' ]); exit; } // Get all the form fields with validation $first_name = validateName($_POST['first_name'] ?? ''); if ($first_name === false) { die('Invalid first name format.'); } $last_name = validateName($_POST['last_name'] ?? ''); if ($last_name === false) { die('Invalid last name format.'); } $id_number = validateSAIDNumber($_POST['id_number'] ?? ''); if ($id_number === false) { die('Invalid ID number format.'); } $dob = validateDate($_POST['dob'] ?? ''); if ($dob === false) { die('Invalid date of birth format.'); } $occupation = sanitizeTextInput($_POST['occupation'] ?? '', 100); $tel_cell = validatePhoneNumber($_POST['tel_cell'] ?? ''); if ($tel_cell === false) { die('Invalid phone number format.'); } $email = validateEmail($_POST['email'] ?? ''); if ($email === false) { die('Invalid email format.'); } // Spouse or Partner details (optional) $spouse_first_name = !empty($_POST['spouse_first_name']) ? validateName($_POST['spouse_first_name']) : null; $spouse_last_name = !empty($_POST['spouse_last_name']) ? validateName($_POST['spouse_last_name']) : null; $spouse_id_number = !empty($_POST['spouse_id_number']) ? validateSAIDNumber($_POST['spouse_id_number']) : null; $spouse_dob = !empty($_POST['spouse_dob']) ? validateDate($_POST['spouse_dob']) : NULL; $spouse_occupation = !empty($_POST['spouse_occupation']) ? sanitizeTextInput($_POST['spouse_occupation'], 100) : null; $spouse_tel_cell = !empty($_POST['spouse_tel_cell']) ? validatePhoneNumber($_POST['spouse_tel_cell']) : null; $spouse_email = !empty($_POST['spouse_email']) ? validateEmail($_POST['spouse_email']) : null; // Children details (optional) $child_name1 = !empty($_POST['child_name1']) ? $_POST['child_name1'] : null; $child_dob1 = !empty($_POST['child_dob1']) ? $_POST['child_dob1'] : null; $child_name2 = !empty($_POST['child_name2']) ? $_POST['child_name2'] : null; $child_dob2 = !empty($_POST['child_dob2']) ? $_POST['child_dob2'] : null; $child_name3 = !empty($_POST['child_name3']) ? $_POST['child_name3'] : null; $child_dob3 = !empty($_POST['child_dob3']) ? $_POST['child_dob3'] : null; // Address and other details $physical_address = $_POST['physical_address']; $postal_address = $_POST['postal_address']; $interests_hobbies = $_POST['interests_hobbies']; // Primary vehicle details $vehicle_make = $_POST['vehicle_make']; $vehicle_model = $_POST['vehicle_model']; $vehicle_year = $_POST['vehicle_year']; $vehicle_registration = $_POST['vehicle_registration']; // Secondary vehicle details (optional) $secondary_vehicle_make = !empty($_POST['secondary_vehicle_make']) ? $_POST['secondary_vehicle_make'] : null; $secondary_vehicle_model = !empty($_POST['secondary_vehicle_model']) ? $_POST['secondary_vehicle_model'] : null; $secondary_vehicle_year = !empty($_POST['secondary_vehicle_year']) ? $_POST['secondary_vehicle_year'] : null; $secondary_vehicle_registration = !empty($_POST['secondary_vehicle_registration']) ? $_POST['secondary_vehicle_registration'] : null; // Start a transaction to ensure data consistency $conn->begin_transaction(); try { // Insert into the member application table $stmt = $conn->prepare("INSERT INTO membership_application ( user_id, first_name, last_name, id_number, dob, occupation, tel_cell, email, spouse_first_name, spouse_last_name, spouse_id_number, spouse_dob, spouse_occupation, spouse_tel_cell, spouse_email, child_name1, child_dob1, child_name2, child_dob2, child_name3, child_dob3, physical_address, postal_address, interests_hobbies, vehicle_make, vehicle_model, vehicle_year, vehicle_registration, secondary_vehicle_make, secondary_vehicle_model, secondary_vehicle_year, secondary_vehicle_registration ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); // Check if preparation was successful if (!$stmt) { die("SQL error: " . $conn->error); } $stmt->bind_param( "isssssssssssssssssssssssssssssss", $user_id, $first_name, $last_name, $id_number, $dob, $occupation, $tel_cell, $email, $spouse_first_name, $spouse_last_name, $spouse_id_number, $spouse_dob, $spouse_occupation, $spouse_tel_cell, $spouse_email, $child_name1, $child_dob1, $child_name2, $child_dob2, $child_name3, $child_dob3, $physical_address, $postal_address, $interests_hobbies, $vehicle_make, $vehicle_model, $vehicle_year, $vehicle_registration, $secondary_vehicle_make, $secondary_vehicle_model, $secondary_vehicle_year, $secondary_vehicle_registration ); if ($stmt->execute()) { // Insert into the membership fees table $today = new DateTime(); $month = (int)$today->format('n'); $year = (int)$today->format('Y'); $payment_date = $today->format('Y-m-d'); $membership_start_date = $payment_date; if ($month == 12 || $month == 1 || $month == 2) { // December, January, February: charge full fee, valid till end of next Feb $payment_amount = getPriceByDescription('membership_fees'); // If Dec, Jan, Feb, set end to next year's Feb $end_year = ($month == 12) ? $year + 2 : $year + 1; $membership_end_date = (new DateTime("$end_year-02-01")) ->modify('last day of this month') ->format('Y-m-d'); } else { // Prorata for Mar-Nov $payment_amount = calculateProrata(getPriceByDescription('pro_rata')); // End of next Feb if after Feb, else this Feb if ($month > 2) { $end_year = $year + 1; } else { $end_year = $year; } $membership_end_date = (new DateTime("$end_year-02-01")) ->modify('last day of this month') ->format('Y-m-d'); } $stmt = $conn->prepare("INSERT INTO membership_fees (user_id, payment_amount, payment_date, membership_start_date, membership_end_date, renewal_period_end, payment_status, payment_id) VALUES (?, ?, ?, ?, ?, ?, 'AWAITING PAYMENT', ?)"); $stmt->bind_param("idsssss", $user_id, $payment_amount, $payment_date, $membership_start_date, $membership_end_date, $membership_end_date, $payment_id); if ($stmt->execute()) { // Commit the transaction $conn->commit(); // Do not create legacy EFTs. Create a payments-ready membership fee and notify admin. // Optionally send an invoice referencing the internal payment id // sendInvoice(getEmail($user_id), getFullName($user_id), $payment_id, formatCurrency($payment_amount), $description); // sendAdminNotification('4WDCSA.co.za - New Membership Application - '.$last_name , 'A new member has signed up, '.$first_name.' '.$last_name); // Audit: membership application submitted if (function_exists('auditLog')) { auditLog($user_id, 'MEMBERSHIP_APPLICATION_SUBMITTED', 'membership_application', null, ['payment_id' => $payment_id, 'amount' => $payment_amount ?? null]); $event = 'new_application_submitted'; $sub_feed = 'membership_applications'; $data = [ 'actor_id' => $_SESSION['user_id'], 'actor_avatar' => $_SESSION['profile_pic'], // used by UI to show avatar 'title' => "New Membership Application from {$first_name} {$last_name}" ]; addNotification(null, $event, $sub_feed, $data, null); } header("Location: indemnity"); // Success message $response = [ 'status' => 'success', 'message' => 'Your membership application has been submitted successfully!' ]; } else { throw new Exception("Failed to insert membership fee. SQL error: " . $conn->error); } } else { throw new Exception("Failed to insert member application.SQL error: " . $conn->error); } } catch (Exception $e) { // Rollback the transaction in case of error $conn->rollback(); // Check for duplicate key error $errorMessage = $e->getMessage(); if (strpos($errorMessage, 'Duplicate') !== false || strpos($errorMessage, '1062') !== false) { $response = [ 'status' => 'error', 'message' => 'You have already submitted a membership application. Please check your email for membership details.' ]; } else { // Error response $response = [ 'status' => 'error', 'message' => 'Error: ' . $errorMessage ]; } } // Return the response in JSON format echo json_encode($response); } ?>