File "sync_from_master.php"

Full path: /home2/santhos2/public_html/bharath-coe.firstmatrix.in.net/api/exam_subjects/sync_from_master.php
File size: 7.77 KiB (7958 bytes)
MIME-type: text/x-php
Charset: utf-8

Download   Open   Back

<?php
require_once '../../config/config.php';
require_once '../helper/audit_log.php';
header('Content-Type: application/json');

// Suppress all error output to ensure clean JSON response
error_reporting(0);
ini_set('display_errors', 0);
ob_start();

try {
    $academicYearId = (int)($_POST['academic_year_id'] ?? 0);
    $regulation = $_POST['regulation'] ?? '';
    $examId = (int)($_POST['exam_id'] ?? 0);
    $courseId = isset($_POST['course_id']) && $_POST['course_id'] !== '' ? (int)$_POST['course_id'] : 0;
    $includeAllSemesters = isset($_POST['include_all_semesters']) ? (int)$_POST['include_all_semesters'] === 1 : false;
    
    if (!$academicYearId || !$regulation || !$examId) {
        echo json_encode(['success' => false, 'message' => 'Academic Year, Regulation, and Exam are required']);
        exit;
    }
    
    // Get the specific exam details
    $examSql = "SELECT e.exam_id, e.exam_name, e.academic_year_id, e.academic_year, e.semester
                FROM exams e
                WHERE e.exam_id = ? AND e.academic_year_id = ?";
    
    $examStmt = $pdo->prepare($examSql);
    $examStmt->execute([$examId, $academicYearId]);
    $exam = $examStmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$exam) {
        echo json_encode(['success' => false, 'message' => 'Exam not found for the selected academic year']);
        exit;
    }
    
    // Get term info from academic_years (Odd/Even)
    $ayStmt = $pdo->prepare('SELECT term_type FROM academic_years WHERE academic_year_id = ?');
    $ayStmt->execute([$academicYearId]);
    $termType = (string)($ayStmt->fetchColumn() ?: '');

    // Build subjects query with optional course filter
    $subjectsSql = "SELECT s.subject_id, s.subject_name, s.subject_code, s.semester, s.regulation_year, c.course_id, c.course_name
                    FROM subjects s
                    LEFT JOIN courses c ON c.course_id = s.course_id
                    WHERE s.regulation_year = ?" . ($courseId > 0 ? " AND s.course_id = ?" : "") . "
                    ORDER BY s.semester, s.subject_name";
    
    $subjectsStmt = $pdo->prepare($subjectsSql);
    $params = [$regulation];
    if ($courseId > 0) { $params[] = $courseId; }
    $subjectsStmt->execute($params);
    $subjects = $subjectsStmt->fetchAll(PDO::FETCH_ASSOC);
    
    if (empty($subjects)) {
        echo json_encode(['success' => false, 'message' => 'No subjects found for the selected regulation']);
        exit;
    }
    
    $totalSynced = 0;
    $totalSkipped = 0;
    $errors = [];
    $syncedSubjects = [];
    $skippedSubjects = [];
    
    // Get subjects filtered by exam semester and/or term parity
    $examSemester = isset($exam['semester']) ? (int)$exam['semester'] : 0;
    $examSubjects = $subjects;
    if (!$includeAllSemesters) {
        if ($examSemester > 0) {
            $examSubjects = array_values(array_filter($examSubjects, function($subject) use ($examSemester) {
                return (int)$subject['semester'] === $examSemester;
            }));
        }
        if ($termType === 'Odd' || $termType === 'Even') {
            $isEven = ($termType === 'Even');
            $examSubjects = array_values(array_filter($examSubjects, function($subject) use ($isEven) {
                $sem = (int)$subject['semester'];
                return ($sem % 2 === 0) === $isEven;
            }));
        }
    }
    
    // Graceful fallback: if no subjects after filters, fallback to all subjects for regulation (and course)
    $fallbackUsed = false;
    if (empty($examSubjects)) {
        $examSubjects = $subjects;
        $fallbackUsed = true;
    }
    
    // Check existing exam subjects for this exam
    $existingSql = "SELECT es.subject_id, s.subject_name, s.regulation_year
                    FROM exam_subjects es
                    JOIN subjects s ON s.subject_id = es.subject_id
                    WHERE es.exam_id = ? AND s.regulation_year = ?";
    
    $existingStmt = $pdo->prepare($existingSql);
    $existingStmt->execute([$examId, $regulation]);
    $existingSubjects = $existingStmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Create array of existing subject IDs for quick lookup
    $existingSubjectIds = array_column($existingSubjects, 'subject_id');
    
    foreach ($examSubjects as $subject) {
        // Check if this subject already exists for this exam with same regulation
        if (in_array($subject['subject_id'], $existingSubjectIds)) {
            $skippedSubjects[] = $subject['subject_name'] . " (already exists)";
            $totalSkipped++;
            continue;
        }
        
        try {
            // Insert the subject into exam_subjects
            $insertSql = "INSERT INTO exam_subjects (exam_id, subject_id, max_marks, pass_marks) 
                         VALUES (?, ?, 100, 40)";
            
            $insertStmt = $pdo->prepare($insertSql);
            $insertStmt->execute([$examId, $subject['subject_id']]);
            
            $totalSynced++;
            $syncedSubjects[] = $subject['subject_name'];
            
        } catch (Exception $e) {
            $errors[] = "Failed to insert subject '{$subject['subject_name']}' for exam '{$exam['exam_name']}': " . $e->getMessage();
        }
    }
    
    // Prepare response
    $response = [
        'success' => true,
        'synced_count' => $totalSynced,
        'skipped_count' => $totalSkipped,
        'total_subjects' => count($subjects),
        'exam_name' => $exam['exam_name'],
        'academic_year' => $exam['academic_year'],
        'regulation' => $regulation,
        'course_id' => $courseId,
        'term_type' => $termType,
        'fallback_used' => isset($fallbackUsed) && $fallbackUsed ? 1 : 0,
        'subjects_considered' => count($examSubjects),
        'synced_subjects' => $syncedSubjects,
        'skipped_subjects' => $skippedSubjects
    ];
    
    if (!empty($errors)) {
        $response['warnings'] = $errors;
    }
    
    // Write comprehensive audit log for bulk sync operation
    write_audit_log($pdo, [
        'module' => 'Exam Management',
        'action' => 'create', // Bulk create operation
        'entity_table' => 'exam_subjects',
        'entity_id' => 'bulk_sync_' . $examId . '_' . time(),
        'after_data' => [
            'exam_id' => $examId,
            'exam_name' => $exam['exam_name'],
            'academic_year_id' => $academicYearId,
            'academic_year' => $exam['academic_year'],
            'regulation' => $regulation,
            'semester' => $exam['semester'],
            'total_subjects_available' => count($subjects),
            'subjects_processed' => count($examSubjects),
            'subjects_synced' => $totalSynced,
            'subjects_skipped' => $totalSkipped,
            'synced_subjects_list' => $syncedSubjects,
            'skipped_subjects_list' => $skippedSubjects,
            'errors' => $errors
        ],
        'message' => "Bulk sync completed: {$totalSynced} subjects synced, {$totalSkipped} skipped for exam '{$exam['exam_name']}' ({$exam['academic_year']})"
    ]);
    
    // Clear any output buffer and send clean JSON
    ob_clean();
    echo json_encode($response);
    
} catch (Exception $e) {
    // Log the error in audit log
    write_audit_log($pdo, [
        'module' => 'Exam Management',
        'action' => 'create',
        'entity_table' => 'exam_subjects',
        'entity_id' => 'bulk_sync_error_' . time(),
        'after_data' => [
            'error_message' => $e->getMessage(),
            'academic_year_id' => $academicYearId ?? 0,
            'regulation' => $regulation ?? '',
            'exam_id' => $examId ?? 0,
            'request_data' => $_POST
        ],
        'message' => 'Bulk sync failed: ' . $e->getMessage()
    ]);
    
    // Clear any output buffer
    ob_clean();
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);
}

ob_end_flush();
?>

PHP File Manager