Mini Shell

Direktori : /home/mhcadmin/public_html/Portal/
Upload File :
Current File : /home/mhcadmin/public_html/Portal/Fees_Upload.php

<?php
session_start();
$rootPath = realpath(dirname(__FILE__) . '/..');
require_once $rootPath . '/Portal/config/config.php';
require_once $rootPath . '/Portal/include/auth_validate.php';

// Memory and execution time limits
ini_set('memory_limit', '128M');
ini_set('max_execution_time', 300);
set_time_limit(300);

// Error reporting
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Check if user is authenticated
if (!isset($_SESSION['id'])) {
    header('Location: login.php');
    exit();
}

$User = $_SESSION['id'];

// Fetch user data
$stmt = mysqli_prepare($conn, "SELECT Access_Level, Full_Name FROM admin_accounts WHERE id = ?");
mysqli_stmt_bind_param($stmt, "i", $User);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);

if (mysqli_num_rows($result) > 0) {
    $rows = mysqli_fetch_assoc($result);
    $UserAccessName = $rows['Access_Level'];
    $FullName = isset($rows['Full_Name']) ? $rows['Full_Name'] : '';
}
mysqli_stmt_close($stmt);

// File upload configuration
$maxFileSize = 5 * 1024 * 1024; // 5MB
$allowedTypes = ['text/csv', 'application/vnd.ms-excel', 'text/plain', 'application/csv'];
$maxRecords = 1000;

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Validate inputs
    $errors = [];
    
    if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
        $errors[] = "File upload failed. Error code: " . ($_FILES['file']['error'] ?? 'Unknown');
    }
    
    // Validate form fields
    $requiredFields = ['Term', 'year'];
    foreach ($requiredFields as $field) {
        if (empty($_POST[$field])) {
            $errors[] = ucfirst(str_replace('_', ' ', $field)) . " is required";
        }
    }
    
    if (empty($errors)) {
        // Sanitize inputs
        $Term = mysqli_real_escape_string($conn, $_POST['Term']);
        $year = mysqli_real_escape_string($conn, $_POST['year']);
        
        // Validate file
        $fileSize = $_FILES['file']['size'];
        $fileType = $_FILES['file']['type'];
        $tmpName = $_FILES['file']['tmp_name'];
        $fileName = $_FILES['file']['name'];
        
        // Check file size
        if ($fileSize > $maxFileSize) {
            $errors[] = "File size exceeds maximum limit of 5MB";
        }
        
        // Check file type (more flexible checking)
        $fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
        if (!in_array($fileType, $allowedTypes) && $fileExtension != 'csv') {
            $errors[] = "Only CSV files are allowed";
        }
        
        if (empty($errors)) {
            // Process CSV file from temporary location without saving
            $processedCount = 0;
            $failedCount = 0;
            $duplicateCount = 0;
            $successfulRecords = [];
            $isFirstRow = true; // Flag to skip header row
            $rowNumber = 1; // For tracking row numbers
            
            // Start transaction
            mysqli_begin_transaction($conn);
            
            try {
                // Open CSV file
                $file = fopen($tmpName, 'r');
                if ($file !== FALSE) {
                    ob_start(); // Start output buffering
                    ?>
                    <html>
                    <?php include_once 'include/AdminHeader.php'; ?>
                    <div id="page-wrapper">
                        <div class="row">
                            <br><br><br>
                        </div>
                    <?php
                    
                    // Read and process the header row to verify column structure
                    $headers = fgetcsv($file, 1000, ",");
                    $expectedHeaders = ['Student_No', 'Full_Name', 'Level', 'Amount_Paid', 'Payment_Mode', 'Reference_No', 'Date_Paid'];
                    
                    // Optional: Verify headers match expected format
                    if ($headers !== FALSE) {
                        // Continue processing data rows
                        while (($data = fgetcsv($file, 1000, ",")) !== FALSE) {
                            $rowNumber++;
                            
                            // Stop if max records reached
                            if ($processedCount >= $maxRecords) {
                                $_SESSION['warning'] = "Upload limited to first {$maxRecords} records.";
                                break;
                            }
                            
                            // Validate CSV row has 7 columns
                            if (count($data) >= 7) {
                                // Clean and escape data
                                $Student_No = isset($data[0]) ? mysqli_real_escape_string($conn, trim($data[0])) : '';
                                $Full_Name = isset($data[1]) ? mysqli_real_escape_string($conn, trim($data[1])) : '';
                                $Level = isset($data[2]) ? mysqli_real_escape_string($conn, trim($data[2])) : '';
                                $Amount_Paid = isset($data[3]) ? mysqli_real_escape_string($conn, trim($data[3])) : '';
                                $Payment_Mode = isset($data[4]) ? mysqli_real_escape_string($conn, trim($data[4])) : '';
                                $Reference_No = isset($data[5]) ? mysqli_real_escape_string($conn, trim($data[5])) : '';
                                
                                // Handle date format conversion (from DD-MMM-YY to YYYY-MM-DD)
                                $Date_Paid_raw = isset($data[6]) ? trim($data[6]) : '';
                                $Date_Paid = convertDateToMySQL($Date_Paid_raw);
                                
                                // Basic validation
                                if (empty($Student_No) || empty($Full_Name) || empty($Level) || empty($Amount_Paid)) {
                                    $failedCount++;
                                } else {
                                    // Check for duplicate record (using Student_No, Amount, Reference, Term, Year)
                                    $checkDuplicateSql = "SELECT COUNT(*) as count FROM fees_payment 
                                                        WHERE Student_NO = '$Student_No' 
                                                        AND Amount = '$Amount_Paid' 
                                                        AND Reference = '$Reference_No'
                                                        AND Term = '$Term'
                                                        AND Year = '$year'";
                                    
                                    $duplicateResult = mysqli_query($conn, $checkDuplicateSql);
                                    if ($duplicateResult) {
                                        $duplicateRow = mysqli_fetch_assoc($duplicateResult);
                                        
                                        if ($duplicateRow['count'] > 0) {
                                            $duplicateCount++;
                                        } else {
                                            // Insert the record (matching database schema)
                                            $insertSql = "INSERT INTO fees_payment 
                                                        (Student_NO, Student_Name, Amount, Payment_Mode, Date_Paid, Reference, Class_Level, Term, Year, CreatedBy) 
                                                         VALUES (
                                                            '$Student_No', 
                                                            '$Full_Name', 
                                                            '$Amount_Paid', 
                                                            '$Payment_Mode', 
                                                            " . ($Date_Paid ? "'$Date_Paid'" : "NULL") . ", 
                                                            '$Reference_No', 
                                                            '$Level', 
                                                            '$Term', 
                                                            '$year', 
                                                            '$User'
                                                        )";
                                            
                                            if (mysqli_query($conn, $insertSql)) {
                                                $processedCount++;
                                                
                                                // Store successful record for display
                                                $successfulRecords[] = [
                                                    'Student_No' => $Student_No,
                                                    'Student_Name' => $Full_Name,
                                                    'Class_Level' => $Level,
                                                    'Amount' => $Amount_Paid,
                                                    'Payment_Mode' => $Payment_Mode,
                                                    'Reference' => $Reference_No,
                                                    'Date_Paid' => $Date_Paid ?: $Date_Paid_raw
                                                ];
                                            } else {
                                                $failedCount++;
                                                // Log the error for debugging
                                                error_log("Insert failed for row $rowNumber: " . mysqli_error($conn));
                                            }
                                        }
                                    } else {
                                        $failedCount++;
                                        error_log("Duplicate check failed for row $rowNumber: " . mysqli_error($conn));
                                    }
                                }
                            } else {
                                $failedCount++;
                                error_log("Row $rowNumber has incorrect number of columns: " . count($data));
                            }
                        }
                    } else {
                        throw new Exception("Failed to read CSV headers");
                    }
                    
                    fclose($file);
                    
                    // Commit transaction if at least one record was inserted
                    if ($processedCount > 0) {
                        mysqli_commit($conn);
                    } else {
                        mysqli_rollback($conn);
                    }
                    
                    // Display summary
                    ?>
                    <div class="row">
                        <div class="col-md-12">
                            
                            <?php
                            // Show flash messages
                            if (file_exists('include/flash_messages.php')) {
                                include('include/flash_messages.php');
                            }
                            ?>
                            
                            <div class="alert alert-info">
                                <h4>Upload Summary</h4>
                                <p><strong>File:</strong> <?php echo htmlspecialchars($fileName); ?></p>
                                <p><strong>Term:</strong> <?php echo htmlspecialchars($Term); ?></p>
                                <p><strong>Year:</strong> <?php echo htmlspecialchars($year); ?></p>
                                <hr>
                                <p>Total Rows Processed: <?php echo ($processedCount + $failedCount + $duplicateCount); ?></p>
                                <p>Successfully Inserted: <span class="text-success"><?php echo $processedCount; ?></span></p>
                                <p>Duplicates Skipped: <span class="text-warning"><?php echo $duplicateCount; ?></span></p>
                                <p>Failed: <span class="text-danger"><?php echo $failedCount; ?></span></p>
                                
                                <?php if ($processedCount == 0 && ($failedCount + $duplicateCount) > 0): ?>
                                <hr>
                                <p><strong>Possible issues:</strong></p>
                                <ul>
                                    <li>Check if CSV file has correct format (7 columns in this order): 
                                        <br><code>Student_No, Full_Name, Level, Amount_Paid, Payment_Mode, Reference_No, Date_Paid</code>
                                    </li>
                                    <li>Date format should be like: 24-Feb-25 (will be converted automatically)</li>
                                    <li>Check if database table "fees_payment" exists with correct columns</li>
                                    <li>Check if you have INSERT permissions on the table</li>
                                    <li>Check PHP error logs for more details</li>
                                </ul>
                                <?php endif; ?>
                            </div>
                            
                            <?php if (!empty($successfulRecords)): ?>
                            <h4>Successfully Uploaded Records:</h4>
                            <div class="table-responsive">
                                <table class="table table-bordered table-hover">
                                    <thead>
                                        <tr>
                                            <th>#</th>
                                            <th>Student No</th>
                                            <th>Student Name</th>
                                            <th>Class Level</th>
                                            <th>Amount Paid</th>
                                            <th>Payment Mode</th>
                                            <th>Reference No</th>
                                            <th>Date Paid</th>
                                            <th>Term</th>
                                            <th>Year</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <?php $counter = 1; ?>
                                        <?php foreach ($successfulRecords as $record): ?>
                                        <tr>
                                            <td><?php echo $counter++; ?></td>
                                            <td><?php echo htmlspecialchars($record['Student_No'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($record['Student_Name'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($record['Class_Level'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($record['Amount'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($record['Payment_Mode'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($record['Reference'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($record['Date_Paid'] ?? ''); ?></td>
                                            <td><?php echo htmlspecialchars($Term); ?></td>
                                            <td><?php echo htmlspecialchars($year); ?></td>
                                        </tr>
                                        <?php endforeach; ?>
                                    </tbody>
                                </table>
                            </div>
                            
                            <!-- Back to Admin Portal button -->
                            <div class="text-center" style="margin-top: 20px; margin-bottom: 20px;">
                                <a href="AdminPortal.php" class="btn btn-primary">Back Home</a>
                                <a href="ManageFeesPayments.php" class="btn btn-info">Manage Fees Payments</a>
                                <a href="javascript:window.print()" class="btn btn-default">Print Report</a>
                            </div>
                            
                            <?php else: ?>
                            <div class="alert alert-warning">
                                <h4>No Records Uploaded</h4>
                                <p>No records were successfully uploaded. This could be due to:</p>
                                <ul>
                                    <li>Empty CSV file</li>
                                    <li>Incorrect CSV format (expected 7 columns)</li>
                                    <li>All records were duplicates</li>
                                    <li>Database connection or permission issues</li>
                                    <li>Date format conversion issues</li>
                                </ul>
                                <p>Please check the CSV file format and try again.</p>
                            </div>
                            
                            <!-- Back to Fees Payment button -->
                            <div class="text-center" style="margin-top: 20px; margin-bottom: 20px;">
                                <a href="ManageFeesPayments.php" class="btn btn-primary">Go Back to Manage Fees</a>
                            </div>
                            <?php endif; ?>
                            
                        </div>
                    </div>
                    </div> <!-- Close page-wrapper -->
                    </html>
                    <?php
                    
                    // Set session messages
                    if ($processedCount > 0) {
                        $_SESSION['success'] = "Fees payments uploaded successfully! Inserted: {$processedCount}, Duplicates: {$duplicateCount}, Failed: {$failedCount}";
                    } else {
                        $_SESSION['failure'] = "No records were uploaded. Total rows processed: " . ($processedCount + $failedCount + $duplicateCount) . ". Please check your CSV file format.";
                    }
                    
                    ob_end_flush(); // Flush output buffer
                    
                } else {
                    throw new Exception("Failed to open uploaded file");
                }
            } catch (Exception $e) {
                // Rollback transaction on error
                mysqli_rollback($conn);
                $_SESSION['failure'] = "Upload failed: " . $e->getMessage();
                header('Location: ManageFeesPayments.php');
                exit();
            }
        }
    }
    
    // If there were errors, redirect back
    if (!empty($errors)) {
        $_SESSION['errors'] = $errors;
        header('Location: ManageFeesPayments.php');
        exit();
    }
} else {
    // Not a POST request, redirect
    header('Location: ManageFeesPayments.php');
    exit();
}

/**
 * Convert date from DD-MMM-YY format to YYYY-MM-DD for MySQL
 * Example: 24-Feb-25 -> 2025-02-24
 */
function convertDateToMySQL($dateString) {
    if (empty($dateString)) {
        return null;
    }
    
    // Remove any extra whitespace
    $dateString = trim($dateString);
    
    // Parse the date format like "24-Feb-25"
    $parts = explode('-', $dateString);
    
    if (count($parts) == 3) {
        $day = $parts[0];
        $month = $parts[1];
        $year = $parts[2];
        
        // Convert month abbreviation to number
        $monthNumbers = [
            'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04',
            'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08',
            'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12'
        ];
        
        $monthNum = isset($monthNumbers[$month]) ? $monthNumbers[$month] : null;
        
        if ($monthNum && is_numeric($day) && is_numeric($year)) {
            // Convert 2-digit year to 4-digit year (25 -> 2025, 24 -> 2024, etc.)
            $fullYear = (strlen($year) == 2) ? '20' . $year : $year;
            
            // Ensure day is 2 digits
            $day = str_pad($day, 2, '0', STR_PAD_LEFT);
            
            return $fullYear . '-' . $monthNum . '-' . $day;
        }
    }
    
    // If parsing fails, return null
    return null;
}
?>