Trying to delete all Data and enter fresh

This commit is contained in:
Flatlogic Bot 2025-12-04 14:07:31 +00:00
parent ef2d9513a5
commit 9a07273b40
5 changed files with 220 additions and 21 deletions

156
admin_data_management.php Normal file
View File

@ -0,0 +1,156 @@
<?php
session_start();
require_once 'includes/auth_check.php';
require_once 'db/config.php';
if ($_SESSION['role'] !== 'admin') {
header('Location: /login.php');
exit;
}
$school_id = $_SESSION['school_id'];
$message = '';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdo = db();
if (isset($_POST['clear_timetable'])) {
try {
$pdo->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.";
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Data Management</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
</head>
<body>
<?php include 'includes/navbar.php'; ?>
<div class="container mt-5">
<h1 class="mb-4">Data Management</h1>
<?php if ($message): ?>
<div class="alert alert-success"><?php echo htmlspecialchars($message); ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<div class="card border-warning mb-4">
<div class="card-header">
<h5 class="mb-0">Clear Timetable Data</h5>
</div>
<div class="card-body">
<p class="card-text">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.</p>
<p class="card-text">This will not delete your classes, subjects, teachers, or workloads.</p>
<form method="POST" onsubmit="return confirm('Are you sure you want to clear all timetable data? This action cannot be undone.');">
<button type="submit" name="clear_timetable" class="btn btn-warning">Clear Timetable Data</button>
</form>
</div>
</div>
<div class="card border-danger">
<div class="card-header">
<h5 class="mb-0">Clear All School Data</h5>
</div>
<div class="card-body">
<p class="card-text text-danger fw-bold"><strong><i class="bi bi-exclamation-triangle-fill"></i> WARNING: This is a destructive action.</strong></p>
<p class="card-text">This action will permanently delete all data associated with your school, including:</p>
<ul>
<li>All Timetable Data</li>
<li>All Workloads</li>
<li>All Teachers</li>
<li>All Subjects</li>
<li>All Classes</li>
<li>All Elective Groups</li>
</ul>
<p class="card-text">Your user account and school registration will not be affected. Use this option only if you want to start over completely.</p>
<form method="POST" onsubmit="return document.getElementById('confirm_delete_checkbox').checked;">
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" value="" id="confirm_delete_checkbox" name="confirm_delete">
<label class="form-check-label" for="confirm_delete_checkbox">
I understand that this action is irreversible and I want to delete all my school's data.
</label>
</div>
<button type="submit" name="clear_all_data" class="btn btn-danger">Delete All School Data</button>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -137,6 +137,21 @@ try {
$error = 'Database error: ' . $e->getMessage(); $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 = '<ul>';
foreach ($unlinked_teachers as $name) {
$unlinked_list .= '<li>' . htmlspecialchars($name) . '</li>';
}
$unlinked_list .= '</ul>';
$error .= '<div class="alert alert-warning mt-3"><strong>Data Inconsistency Found:</strong> 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.</div>';
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@ -245,7 +260,12 @@ try {
<tbody> <tbody>
<?php foreach ($teachers as $teacher): ?> <?php foreach ($teachers as $teacher): ?>
<tr> <tr>
<td><?php echo htmlspecialchars($teacher['name']); ?></td> <td>
<?php echo htmlspecialchars($teacher['name']); ?>
<?php if (empty($teacher['user_id'])): ?>
<span class="badge bg-danger" title="This teacher is not linked to a user account.">!</span>
<?php endif; ?>
</td>
<td><?php echo htmlspecialchars($teacher['email']); ?></td> <td><?php echo htmlspecialchars($teacher['email']); ?></td>
<td> <td>
<a href="?edit_id=<?php echo $teacher['id']; ?>" class="btn btn-sm btn-outline-primary">Edit</a> <a href="?edit_id=<?php echo $teacher['id']; ?>" class="btn btn-sm btn-outline-primary">Edit</a>

View File

@ -25,6 +25,8 @@ $role = $_SESSION['role'] ?? '';
<li><a class="dropdown-item" href="/admin_workloads.php">Workloads</a></li> <li><a class="dropdown-item" href="/admin_workloads.php">Workloads</a></li>
<li><a class="dropdown-item" href="/admin_timeslots.php">Timeslots</a></li> <li><a class="dropdown-item" href="/admin_timeslots.php">Timeslots</a></li>
<li><a class="dropdown-item" href="/admin_elective_groups.php">Elective Groups</a></li> <li><a class="dropdown-item" href="/admin_elective_groups.php">Elective Groups</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="/admin_data_management.php">Data Management</a></li>
</ul> </ul>
</li> </li>
<li class="nav-item"><a class="nav-link <?php echo ($current_page == 'timetable.php') ? 'active' : ''; ?>" href="/timetable.php">Class Timetable</a></li> <li class="nav-item"><a class="nav-link <?php echo ($current_page == 'timetable.php') ? 'active' : ''; ?>" href="/timetable.php">Class Timetable</a></li>

View File

@ -27,7 +27,7 @@ function get_teacher_schedule($pdo, $teacher_id, $school_id) {
FROM schedules s FROM schedules s
JOIN classes c ON s.class_id = c.id JOIN classes c ON s.class_id = c.id
JOIN schedule_teachers st ON s.id = st.schedule_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]); $stmt->execute([':teacher_id' => $teacher_id, ':school_id' => $school_id]);
return $stmt->fetchAll(PDO::FETCH_ASSOC); return $stmt->fetchAll(PDO::FETCH_ASSOC);

View File

@ -4,14 +4,25 @@ require_once 'includes/auth_check.php';
require_once 'db/config.php'; require_once 'db/config.php';
// --- Database Fetch --- // --- Database Fetch ---
function get_all_data($pdo) { function get_all_data($pdo, $school_id) {
$data = []; $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); $stmt_classes = $pdo->prepare("SELECT * FROM classes WHERE school_id = ? ORDER BY name");
$data['teachers'] = $pdo->query("SELECT id, name FROM teachers")->fetchAll(PDO::FETCH_KEY_PAIR); $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); $data['timeslots'] = $pdo->query("SELECT * FROM timeslots ORDER BY start_time")->fetchAll(PDO::FETCH_ASSOC);
$workloads_stmt = $pdo->query(" $workloads_stmt = $pdo->prepare("
SELECT SELECT
w.class_id, w.subject_id, w.teacher_id, w.lessons_per_week, 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, 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 classes c ON w.class_id = c.id
JOIN teachers t ON w.teacher_id = t.id JOIN teachers t ON w.teacher_id = t.id
LEFT JOIN elective_groups eg ON s.elective_group_id = eg.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); $data['workloads'] = $workloads_stmt->fetchAll(PDO::FETCH_ASSOC);
return $data; return $data;
@ -200,17 +213,17 @@ function find_best_slot_for_lesson($lesson, &$class_timetables, &$teacher_timeta
// --- Timetable Persistence --- // --- Timetable Persistence ---
function save_timetable($pdo, $class_timetables, $timeslots) { function save_timetable($pdo, $class_timetables, $timeslots, $school_id) {
try { try {
$pdo->beginTransaction(); $pdo->beginTransaction();
$pdo->exec('SET FOREIGN_KEY_CHECKS=0');
$pdo->exec('TRUNCATE TABLE schedule_teachers'); // Safer delete: only remove schedules for the current school
$pdo->exec('TRUNCATE TABLE schedules'); $delete_stmt = $pdo->prepare('DELETE FROM schedules WHERE school_id = ?');
$pdo->exec('SET FOREIGN_KEY_CHECKS=1'); $delete_stmt->execute([$school_id]);
$stmt = $pdo->prepare( $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) ' . '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)' '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( $teacher_stmt = $pdo->prepare(
'INSERT INTO schedule_teachers (schedule_id, teacher_id) VALUES (:schedule_id, :teacher_id)' '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, ':lesson_display_name' => $display_name,
':teacher_display_name' => $lesson['teacher_name'], ':teacher_display_name' => $lesson['teacher_name'],
':is_double' => (int)$lesson['is_double'], ':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(); $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) { foreach ($lesson['teacher_ids'] as $teacher_id) {
$teacher_stmt->execute([':schedule_id' => $schedule_id, ':teacher_id' => $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) { function get_timetable_from_db($pdo, $classes, $timeslots, $school_id) {
$stmt = $pdo->query('SELECT * FROM schedules ORDER BY id'); $stmt = $pdo->prepare('SELECT * FROM schedules WHERE school_id = ? ORDER BY id');
$stmt->execute([$school_id]);
$saved_lessons = $stmt->fetchAll(PDO::FETCH_ASSOC); $saved_lessons = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($saved_lessons)) return []; if (empty($saved_lessons)) return [];
@ -305,7 +324,9 @@ function get_timetable_from_db($pdo, $classes, $timeslots) {
// --- Main Logic --- // --- Main Logic ---
$pdoconn = db(); $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']; $classes = $all_data['classes'];
$timeslots = $all_data['timeslots']; $timeslots = $all_data['timeslots'];
$workloads = $all_data['workloads']; $workloads = $all_data['workloads'];
@ -316,10 +337,10 @@ $class_timetables = [];
if (isset($_POST['generate'])) { if (isset($_POST['generate'])) {
if (!empty($workloads)) { if (!empty($workloads)) {
$class_timetables = generate_timetable($all_data, $days_of_week); $class_timetables = generate_timetable($all_data, $days_of_week);
save_timetable($pdoconn, $class_timetables, $timeslots); save_timetable($pdoconn, $class_timetables, $timeslots, $school_id);
} }
} else { } else {
$class_timetables = get_timetable_from_db($pdoconn, $classes, $timeslots); $class_timetables = get_timetable_from_db($pdoconn, $classes, $timeslots, $school_id);
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -433,4 +454,4 @@ if (isset($_POST['generate'])) {
}); });
</script> </script>
</body> </body>
</html> </html>