83 lines
3.6 KiB
PHP
83 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.sla_paused_at IS NULL
|
||
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']]);
|
||
ticket_sla_log_overdue($pdo, (int) $t['id'], 'resolution', (string) $t['resolution_due_at']);
|
||
log_activity($pdo, $t['id'], null, 'SLA überschritten – Ticket als überfällig markiert');
|
||
|
||
// Nur die Betroffenen bekommen eine Mail (Bearbeiter bzw. Abteilung), nicht die Postfach-Adresse der Abteilung und nicht alle Admins
|
||
notify_overdue_ticket_staff($t);
|
||
fcm_notify_overdue($t); // Push auf die Android-App
|
||
$newlyOverdue++;
|
||
if ($verbose) {
|
||
$log[] = "[ok] Ticket #{$t['ticket_number']} als überfällig markiert";
|
||
}
|
||
}
|
||
}
|
||
|
||
$responseStmt = $pdo->prepare("SELECT id, first_response_due_at FROM tickets
|
||
WHERE first_responded_at IS NULL AND first_response_due_at IS NOT NULL AND first_response_due_at < ?
|
||
AND sla_paused_at IS NULL AND status NOT IN ('resolved','closed')");
|
||
$responseStmt->execute([$now]);
|
||
foreach ($responseStmt->fetchAll() as $ticket) ticket_sla_log_overdue($pdo, (int) $ticket['id'], 'first_response', (string) $ticket['first_response_due_at']);
|
||
|
||
// 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";
|
||
}
|
||
}
|