37970-vm/notifications.php
Flatlogic Bot 57a1969d5e v4
2026-01-30 14:56:15 +00:00

197 lines
8.6 KiB
PHP

<?php
require_once __DIR__ . '/db/config.php';
require_once __DIR__ . '/mail/MailService.php';
require_once __DIR__ . '/ai/LocalAIApi.php';
session_start();
// Auth Check
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'Admin') {
header('Location: login.php');
exit;
}
$db = db();
$school_id = $_SESSION['school_id'];
$pageTitle = 'Automated Notifications | SOMS';
$message = '';
$error = '';
// Default threshold
$threshold = isset($_GET['threshold']) ? (int)$_GET['threshold'] : 50;
// Fetch learners with their averages
$query = "
SELECT
l.id,
l.full_name,
l.student_id,
l.parent_email,
l.grade,
AVG((m.marks_obtained / a.total_marks) * 100) as average_percent
FROM learners l
JOIN marks m ON l.id = m.learner_id
JOIN assessments a ON m.assessment_id = a.id
WHERE l.school_id = ?
GROUP BY l.id
HAVING average_percent < ?
";
$stmt = $db->prepare($query);
$stmt->execute([$school_id, $threshold]);
$low_performers = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (isset($_POST['send_notifications'])) {
$sent_count = 0;
$fail_count = 0;
$use_ai = isset($_POST['use_ai']);
foreach ($low_performers as $learner) {
if (empty($learner['parent_email'])) {
$fail_count++;
continue;
}
$avg = round($learner['average_percent'], 1);
$subject = "Urgent: Academic Progress Report for " . $learner['full_name'];
$htmlBody = "
<h3>Academic Progress Alert</h3>
<p>Dear Parent,</p>
<p>This is an automated notification regarding the academic performance of <strong>{$learner['full_name']}</strong> (ID: {$learner['student_id']}).</p>
<p>The current academic average is <strong>{$avg}%</strong>, which is below the school's monitoring threshold of {$threshold}%.</p>
<p>We encourage you to log into the Parent Portal using the Student ID to view detailed assessment marks and discuss this with the class teacher.</p>
<p>Best Regards,<br>School Administration</p>
";
if ($use_ai) {
$ai_prompt = "Generate a short, encouraging, and supportive email to a parent whose child, {$learner['full_name']}, is currently averaging {$avg}% in school (threshold is {$threshold}%). The tone should be professional yet empathetic. Mention that they can check the portal with ID {$learner['student_id']}. Keep it under 150 words.";
$ai_resp = LocalAIApi::createResponse([
'input' => [
['role' => 'system', 'content' => 'You are an educational assistant helping schools communicate with parents.'],
['role' => 'user', 'content' => $ai_prompt],
],
]);
if (!empty($ai_resp['success'])) {
$ai_text = LocalAIApi::extractText($ai_resp);
if ($ai_text) {
$htmlBody = nl2br(htmlspecialchars($ai_text));
}
}
}
$res = MailService::sendMail($learner['parent_email'], $subject, $htmlBody);
if (!empty($res['success'])) {
$sent_count++;
} else {
$fail_count++;
}
}
$message = "Successfully sent $sent_count notifications. (Failed/Missing Email: $fail_count)";
// Refresh list
$stmt->execute([$school_id, $threshold]);
$low_performers = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
include 'includes/header.php';
?>
<div class="container pb-5">
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="admin.php">Dashboard</a></li>
<li class="breadcrumb-item active" aria-current="page">Notifications</li>
</ol>
</nav>
<h2 class="h4 mb-1">Automated Performance Notifications</h2>
<p class="text-muted small">Notify parents of learners performing below a specific threshold.</p>
</div>
</div>
<div class="row g-4">
<div class="col-md-4">
<div class="card shadow-sm border-0 mb-4">
<div class="card-body">
<h5 class="fw-bold mb-3">Settings</h5>
<form action="notifications.php" method="GET" class="mb-4">
<label class="form-label small fw-bold">Performance Threshold (%)</label>
<div class="input-group">
<input type="number" name="threshold" class="form-control" value="<?= $threshold ?>" min="1" max="100">
<button class="btn btn-outline-primary" type="submit">Update List</button>
</div>
<div class="form-text small">Currently showing learners with average < <?= $threshold ?>%</div>
</form>
<form action="notifications.php?threshold=<?= $threshold ?>" method="POST">
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" name="use_ai" id="useAi" checked>
<label class="form-check-label small" for="useAi">Use AI to personalize messages</label>
</div>
<div class="d-grid">
<button type="submit" name="send_notifications" class="btn btn-primary" <?= empty($low_performers) ? 'disabled' : '' ?>>
<i class="bi bi-send me-2"></i> Send to <?= count($low_performers) ?> Parents
</button>
</div>
</form>
</div>
</div>
<div class="alert alert-info small border-0 shadow-sm">
<i class="bi bi-info-circle me-2"></i> Only learners with a <strong>Parent Email</strong> defined will receive notifications.
</div>
</div>
<div class="col-md-8">
<div class="card shadow-sm border-0">
<div class="card-header bg-white py-3">
<h5 class="mb-0 fw-bold">Learners Below Threshold (<?= $threshold ?>%)</h5>
</div>
<div class="card-body p-0">
<?php if ($message): ?>
<div class="alert alert-success m-3 small"><?= $message ?></div>
<?php endif; ?>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th class="ps-3">Learner</th>
<th>Grade</th>
<th>Average</th>
<th>Parent Email</th>
</tr>
</thead>
<tbody>
<?php if (empty($low_performers)): ?>
<tr>
<td colspan="4" class="text-center py-4 text-muted small">No learners found below this threshold.</td>
</tr>
<?php endif; ?>
<?php foreach ($low_performers as $learner): ?>
<tr>
<td class="ps-3">
<div class="fw-bold"><?= htmlspecialchars($learner['full_name']) ?></div>
<div class="text-muted small">ID: <?= htmlspecialchars($learner['student_id']) ?></div>
</td>
<td>Grade <?= htmlspecialchars($learner['grade']) ?></td>
<td>
<span class="badge bg-danger"><?= round($learner['average_percent'], 1) ?>%</span>
</td>
<td class="small">
<?= $learner['parent_email'] ? htmlspecialchars($learner['parent_email']) : '<span class="text-danger italic">Missing</span>' ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<?php include 'includes/footer.php'; ?>