Files
deskhub/DeskHub-Webseite/cron/check_sla.php
T
2026-10-21 16:44:44 +00:00

82 lines
3.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// Direkter Web-Zugriff (Browser/URL) wird geblockt. Ausnahmen: echter CLI-Cronjob
// sowie Einbindung per require_once aus dem authentifizierten Backend (staff/settings.php),
// das vor dem require_once die Konstante DESKHUB_CRON_RUNNER definiert.
if (php_sapi_name() !== 'cli' && !defined('DESKHUB_CRON_RUNNER')) { http_response_code(403); exit('Kein Web-Zugriff.'); }
/**
* cron/check_sla.php
*
* Prüft alle offenen Tickets auf überschrittene SLA-Fristen (Erstreaktion
* und Lösung) und markiert sie als überfällig (is_overdue). Optional kann
* bei neu erkannter Überfälligkeit eine Eskalations-E-Mail an die
* zuständige Abteilung gesendet werden.
*
* Einrichtung: Per Cronjob alle 15 Minuten aufrufen (Crontab-Beispiel siehe README.md):
* /usr/bin/php /pfad/zu/deskhub/cron/check_sla.php >> /pfad/zu/deskhub/cron/check_sla.log 2>&1
*
* Kann außerdem manuell aus dem Backend (Einstellungen → Cron-Jobs) ausgeführt werden.
*/
require_once __DIR__ . '/../includes/bootstrap.php';
/**
* Führt die SLA-Prüfung aus. Kann vom Cron und manuell aus settings.php aufgerufen werden.
*
* @return array{overdueTotal: int, newlyOverdue: int, log: string[]}
*/
function run_check_sla(PDO $pdo, bool $verbose = false): array
{
$now = db_now();
$stmt = $pdo->prepare(
"SELECT t.*, d.email AS department_email, d.name AS department_name FROM tickets t
JOIN departments d ON d.id = t.department_id
WHERE t.status NOT IN ('resolved','closed')
AND t.resolution_due_at IS NOT NULL
AND t.resolution_due_at < ?"
);
$stmt->execute([$now]);
$overdue = $stmt->fetchAll();
$newlyOverdue = 0;
$log = [];
foreach ($overdue as $t) {
if (!$t['is_overdue']) {
$pdo->prepare('UPDATE tickets SET is_overdue = 1 WHERE id = ?')->execute([$t['id']]);
log_activity($pdo, $t['id'], null, 'SLA überschritten – Ticket als überfällig markiert');
if ($t['department_email']) {
$subject = "SLA überschritten: Ticket #{$t['ticket_number']}";
$inner = email_p('Das folgende Ticket hat die SLA-Lösungsfrist überschritten und benötigt Aufmerksamkeit:')
. email_badge('Ticket', '#' . $t['ticket_number'], '#b91c1c', '#fee2e2')
. email_p('<strong>Betreff:</strong> ' . e($t['subject']), '24px')
. email_button('Ticket ansehen', e(base_url() . '/staff/ticket_view.php?n=' . urlencode($t['ticket_number'])), '#dc2626');
email_send_and_log($t['department_email'], $subject, email_wrap($inner), null, 'SLA-überschritten-Mail (Abteilung)', $t['ticket_number']);
}
notify_admins_overdue_ticket($t);
fcm_notify_overdue($t); // Push auf die Android-App
$newlyOverdue++;
if ($verbose) {
$log[] = "[ok] Ticket #{$t['ticket_number']} als überfällig markiert";
}
}
}
// Tickets, die nicht mehr überfällig sind (z.B. weil sie gelöst wurden), zurücksetzen
$pdo->exec("UPDATE tickets SET is_overdue = 0 WHERE status IN ('resolved','closed') AND is_overdue = 1");
set_setting('cron_check_sla_last_run', $now);
$log[] = "[" . date('Y-m-d H:i:s') . "] SLA-Prüfung abgeschlossen. " . count($overdue) . " überfällige Tickets insgesamt, davon {$newlyOverdue} neu erkannt.";
return ['overdueTotal' => count($overdue), 'newlyOverdue' => $newlyOverdue, 'log' => $log];
}
if (php_sapi_name() === 'cli') {
$result = run_check_sla(get_db(), true);
foreach ($result['log'] as $line) {
echo $line . "\n";
}
}