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
<?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();
?>