82 lines
3.6 KiB
PHP
82 lines
3.6 KiB
PHP
<?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";
|
||
}
|
||
}
|