diff --git a/admin_data_management.php b/admin_data_management.php new file mode 100644 index 0000000..e2c4e36 --- /dev/null +++ b/admin_data_management.php @@ -0,0 +1,156 @@ +beginTransaction(); + + $stmt = $pdo->prepare("DELETE FROM schedule_teachers WHERE schedule_id IN (SELECT id FROM schedules WHERE school_id = ?)"); + $stmt->execute([$school_id]); + + $stmt = $pdo->prepare("DELETE FROM schedules WHERE school_id = ?"); + $stmt->execute([$school_id]); + + $pdo->commit(); + $message = "Timetable data has been successfully cleared."; + } catch (Exception $e) { + $pdo->rollBack(); + $error = "An error occurred while clearing timetable data: " . $e->getMessage(); + } + } + + if (isset($_POST['clear_all_data'])) { + if (isset($_POST['confirm_delete'])) { + try { + $pdo->beginTransaction(); + + // Order of deletion is important to avoid foreign key constraint errors + $tables_to_clear = [ + 'schedule_teachers', + 'schedules', + 'workloads', + 'elective_group_subjects', + 'teachers', // Teachers might be referenced by workloads + 'subjects', // Subjects are referenced by many tables + 'elective_groups', + 'classes' + ]; + + // First, delete from linking tables based on schedule_id + $stmt = $pdo->prepare("DELETE FROM schedule_teachers WHERE schedule_id IN (SELECT id FROM schedules WHERE school_id = ?)"); + $stmt->execute([$school_id]); + + // Now delete from the main tables with a school_id + $stmt = $pdo->prepare("DELETE FROM schedules WHERE school_id = ?"); + $stmt->execute([$school_id]); + $stmt = $pdo->prepare("DELETE FROM workloads WHERE school_id = ?"); + $stmt->execute([$school_id]); + + // elective_group_subjects links subjects and elective_groups + $stmt = $pdo->prepare("DELETE egs FROM elective_group_subjects egs JOIN subjects s ON egs.subject_id = s.id WHERE s.school_id = ?"); + $stmt->execute([$school_id]); + + $stmt = $pdo->prepare("DELETE FROM teachers WHERE school_id = ?"); + $stmt->execute([$school_id]); + $stmt = $pdo->prepare("DELETE FROM subjects WHERE school_id = ?"); + $stmt->execute([$school_id]); + $stmt = $pdo->prepare("DELETE FROM elective_groups WHERE class_id IN (SELECT id FROM classes WHERE school_id = ?)"); + $stmt->execute([$school_id]); + $stmt = $pdo->prepare("DELETE FROM classes WHERE school_id = ?"); + $stmt->execute([$school_id]); + + $pdo->commit(); + $message = "All school data has been successfully cleared."; + } catch (Exception $e) { + $pdo->rollBack(); + $error = "An error occurred while clearing all data: " . $e->getMessage(); + } + } else { + $error = "Please check the confirmation box to proceed with deleting all data."; + } + } +} + +?> + + + + + + Data Management + + + + + + +
+

Data Management

+ + +
+ + +
+ + +
+
+
Clear Timetable Data
+
+
+

This action will delete all generated timetable entries (`schedules` and `schedule_teachers`) for your school. This is useful if you want to regenerate the timetable from scratch or if you are unable to delete other items like classes or subjects due to database constraints.

+

This will not delete your classes, subjects, teachers, or workloads.

+
+ +
+
+
+ +
+
+
Clear All School Data
+
+
+

WARNING: This is a destructive action.

+

This action will permanently delete all data associated with your school, including:

+
    +
  • All Timetable Data
  • +
  • All Workloads
  • +
  • All Teachers
  • +
  • All Subjects
  • +
  • All Classes
  • +
  • All Elective Groups
  • +
+

Your user account and school registration will not be affected. Use this option only if you want to start over completely.

+
+
+ + +
+ +
+
+
+ +
+ + + + diff --git a/admin_teachers.php b/admin_teachers.php index 3f22fba..3af3e08 100644 --- a/admin_teachers.php +++ b/admin_teachers.php @@ -137,6 +137,21 @@ try { $error = 'Database error: ' . $e->getMessage(); } +// Check for teachers with no user account linked +$unlinked_teachers = []; +foreach ($teachers as $teacher) { + if (empty($teacher['user_id'])) { + $unlinked_teachers[] = $teacher['name']; + } +} +if (!empty($unlinked_teachers)) { + $unlinked_list = ''; + $error .= '
Data Inconsistency Found: The following teachers are not linked to a user account and will not be able to log in or see their timetables: ' . $unlinked_list . ' To fix this, please delete these teachers and create them again. This will create a linked user account for them.
'; +} ?> @@ -245,7 +260,12 @@ try { - + + + + ! + + Edit diff --git a/includes/navbar.php b/includes/navbar.php index 842197e..4ce32cd 100644 --- a/includes/navbar.php +++ b/includes/navbar.php @@ -25,6 +25,8 @@ $role = $_SESSION['role'] ?? '';
  • Workloads
  • Timeslots
  • Elective Groups
  • +
  • +
  • Data Management
  • diff --git a/teacher_timetable.php b/teacher_timetable.php index 6007ac7..17e7799 100644 --- a/teacher_timetable.php +++ b/teacher_timetable.php @@ -27,7 +27,7 @@ function get_teacher_schedule($pdo, $teacher_id, $school_id) { FROM schedules s JOIN classes c ON s.class_id = c.id JOIN schedule_teachers st ON s.id = st.schedule_id - WHERE st.teacher_id = :teacher_id AND c.school_id = :school_id + WHERE st.teacher_id = :teacher_id AND s.school_id = :school_id "); $stmt->execute([':teacher_id' => $teacher_id, ':school_id' => $school_id]); return $stmt->fetchAll(PDO::FETCH_ASSOC); diff --git a/timetable.php b/timetable.php index 654b302..a6d7d65 100644 --- a/timetable.php +++ b/timetable.php @@ -4,14 +4,25 @@ require_once 'includes/auth_check.php'; require_once 'db/config.php'; // --- Database Fetch --- -function get_all_data($pdo) { +function get_all_data($pdo, $school_id) { $data = []; - $data['classes'] = $pdo->query("SELECT * FROM classes ORDER BY name")->fetchAll(PDO::FETCH_ASSOC); - $data['subjects'] = $pdo->query("SELECT id, name FROM subjects")->fetchAll(PDO::FETCH_KEY_PAIR); - $data['teachers'] = $pdo->query("SELECT id, name FROM teachers")->fetchAll(PDO::FETCH_KEY_PAIR); + + $stmt_classes = $pdo->prepare("SELECT * FROM classes WHERE school_id = ? ORDER BY name"); + $stmt_classes->execute([$school_id]); + $data['classes'] = $stmt_classes->fetchAll(PDO::FETCH_ASSOC); + + $stmt_subjects = $pdo->prepare("SELECT id, name FROM subjects WHERE school_id = ?"); + $stmt_subjects->execute([$school_id]); + $data['subjects'] = $stmt_subjects->fetchAll(PDO::FETCH_KEY_PAIR); + + $stmt_teachers = $pdo->prepare("SELECT id, name FROM teachers WHERE school_id = ?"); + $stmt_teachers->execute([$school_id]); + $data['teachers'] = $stmt_teachers->fetchAll(PDO::FETCH_KEY_PAIR); + + // Timeslots are not school-specific in the current schema $data['timeslots'] = $pdo->query("SELECT * FROM timeslots ORDER BY start_time")->fetchAll(PDO::FETCH_ASSOC); - $workloads_stmt = $pdo->query(" + $workloads_stmt = $pdo->prepare(" SELECT w.class_id, w.subject_id, w.teacher_id, w.lessons_per_week, s.name as subject_name, s.has_double_lesson, s.elective_group_id, @@ -23,7 +34,9 @@ function get_all_data($pdo) { JOIN classes c ON w.class_id = c.id JOIN teachers t ON w.teacher_id = t.id LEFT JOIN elective_groups eg ON s.elective_group_id = eg.id + WHERE w.school_id = ? "); + $workloads_stmt->execute([$school_id]); $data['workloads'] = $workloads_stmt->fetchAll(PDO::FETCH_ASSOC); return $data; @@ -200,17 +213,17 @@ function find_best_slot_for_lesson($lesson, &$class_timetables, &$teacher_timeta // --- Timetable Persistence --- -function save_timetable($pdo, $class_timetables, $timeslots) { +function save_timetable($pdo, $class_timetables, $timeslots, $school_id) { try { $pdo->beginTransaction(); - $pdo->exec('SET FOREIGN_KEY_CHECKS=0'); - $pdo->exec('TRUNCATE TABLE schedule_teachers'); - $pdo->exec('TRUNCATE TABLE schedules'); - $pdo->exec('SET FOREIGN_KEY_CHECKS=1'); + + // Safer delete: only remove schedules for the current school + $delete_stmt = $pdo->prepare('DELETE FROM schedules WHERE school_id = ?'); + $delete_stmt->execute([$school_id]); $stmt = $pdo->prepare( - 'INSERT INTO schedules (class_id, day_of_week, timeslot_id, subject_id, lesson_display_name, teacher_display_name, is_double, is_elective) ' . - 'VALUES (:class_id, :day_of_week, :timeslot_id, :subject_id, :lesson_display_name, :teacher_display_name, :is_double, :is_elective)' + 'INSERT INTO schedules (class_id, day_of_week, timeslot_id, subject_id, lesson_display_name, teacher_display_name, is_double, is_elective, school_id) ' . + 'VALUES (:class_id, :day_of_week, :timeslot_id, :subject_id, :lesson_display_name, :teacher_display_name, :is_double, :is_elective, :school_id)' ); $teacher_stmt = $pdo->prepare( 'INSERT INTO schedule_teachers (schedule_id, teacher_id) VALUES (:schedule_id, :teacher_id)' @@ -235,11 +248,16 @@ function save_timetable($pdo, $class_timetables, $timeslots) { ':lesson_display_name' => $display_name, ':teacher_display_name' => $lesson['teacher_name'], ':is_double' => (int)$lesson['is_double'], - ':is_elective' => (int)$lesson['is_elective'] + ':is_elective' => (int)$lesson['is_elective'], + ':school_id' => $school_id ]); $schedule_id = $pdo->lastInsertId(); + // Before inserting into schedule_teachers, we need to delete old entries for this schedule_id + // This is implicitly handled by the school-wide delete at the beginning. + // However, if we were not doing a full delete, we would need to clear old teachers for this lesson. + foreach ($lesson['teacher_ids'] as $teacher_id) { $teacher_stmt->execute([':schedule_id' => $schedule_id, ':teacher_id' => $teacher_id]); } @@ -259,8 +277,9 @@ function save_timetable($pdo, $class_timetables, $timeslots) { } } -function get_timetable_from_db($pdo, $classes, $timeslots) { - $stmt = $pdo->query('SELECT * FROM schedules ORDER BY id'); +function get_timetable_from_db($pdo, $classes, $timeslots, $school_id) { + $stmt = $pdo->prepare('SELECT * FROM schedules WHERE school_id = ? ORDER BY id'); + $stmt->execute([$school_id]); $saved_lessons = $stmt->fetchAll(PDO::FETCH_ASSOC); if (empty($saved_lessons)) return []; @@ -305,7 +324,9 @@ function get_timetable_from_db($pdo, $classes, $timeslots) { // --- Main Logic --- $pdoconn = db(); -$all_data = get_all_data($pdoconn); +$school_id = $_SESSION['school_id']; // Get school_id from session + +$all_data = get_all_data($pdoconn, $school_id); $classes = $all_data['classes']; $timeslots = $all_data['timeslots']; $workloads = $all_data['workloads']; @@ -316,10 +337,10 @@ $class_timetables = []; if (isset($_POST['generate'])) { if (!empty($workloads)) { $class_timetables = generate_timetable($all_data, $days_of_week); - save_timetable($pdoconn, $class_timetables, $timeslots); + save_timetable($pdoconn, $class_timetables, $timeslots, $school_id); } } else { - $class_timetables = get_timetable_from_db($pdoconn, $classes, $timeslots); + $class_timetables = get_timetable_from_db($pdoconn, $classes, $timeslots, $school_id); } ?> @@ -433,4 +454,4 @@ if (isset($_POST['generate'])) { }); - + \ No newline at end of file