74 lines
3.0 KiB
PHP
74 lines
3.0 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/auto_close_tickets.php
|
||
*
|
||
* Schließt Tickets automatisch, die seit "Mitarbeiter hat geantwortet, Kunde
|
||
* hat sich nicht mehr gemeldet" (Status "answered") länger als die
|
||
* eingestellte Anzahl Tage nicht mehr aktualisiert wurden. Abschaltbar
|
||
* (Standard: aus) und die Anzahl Tage einstellbar unter Einstellungen →
|
||
* Allgemein → "Tickets automatisch schließen".
|
||
*
|
||
* Einrichtung: Per Cronjob z.B. einmal täglich aufrufen (Crontab-Beispiel siehe README.md):
|
||
* /usr/bin/php /pfad/zu/deskhub/cron/auto_close_tickets.php >> /pfad/zu/deskhub/cron/auto_close_tickets.log 2>&1
|
||
*
|
||
* Kann außerdem manuell aus dem Backend (Einstellungen → Cron-Jobs) ausgeführt werden.
|
||
*/
|
||
|
||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||
|
||
/**
|
||
* Führt das automatische Schließen aus. Kann vom Cron und manuell aus settings.php aufgerufen werden.
|
||
*
|
||
* @return array{closed: int, log: string[]}
|
||
*/
|
||
function run_auto_close_tickets(PDO $pdo, bool $verbose = false): array
|
||
{
|
||
$log = [];
|
||
|
||
if (get_setting('auto_close_enabled', '0') !== '1') {
|
||
$log[] = '[' . date('Y-m-d H:i:s') . '] Automatisches Schließen ist deaktiviert – nichts zu tun.';
|
||
return ['closed' => 0, 'log' => $log];
|
||
}
|
||
|
||
$days = max(1, (int) get_setting('auto_close_days', '7'));
|
||
$threshold = date('Y-m-d H:i:s', time() - $days * 86400);
|
||
|
||
// Nur Tickets, bei denen der Mitarbeiter zuletzt geantwortet hat (status='answered')
|
||
// und der Kunde sich seitdem nicht mehr gemeldet hat (sonst wäre der Status längst
|
||
// wieder 'open') – exakt der in der Anfrage beschriebene Fall "keine Reaktion".
|
||
$stmt = $pdo->prepare(
|
||
"SELECT id, ticket_number FROM tickets
|
||
WHERE status = 'answered' AND is_spam = 0 AND updated_at < ?"
|
||
);
|
||
$stmt->execute([$threshold]);
|
||
$tickets = $stmt->fetchAll();
|
||
|
||
$now = db_now();
|
||
$closed = 0;
|
||
foreach ($tickets as $t) {
|
||
$pdo->prepare("UPDATE tickets SET status = 'closed', closed_at = ?, updated_at = ? WHERE id = ?")
|
||
->execute([$now, $now, $t['id']]);
|
||
log_activity($pdo, (int) $t['id'], null, "Automatisch geschlossen (keine Kundenreaktion seit {$days} Tagen)");
|
||
$closed++;
|
||
if ($verbose) {
|
||
$log[] = "[ok] Ticket #{$t['ticket_number']} automatisch geschlossen";
|
||
}
|
||
}
|
||
|
||
set_setting('cron_auto_close_tickets_last_run', $now);
|
||
$log[] = '[' . date('Y-m-d H:i:s') . "] Automatisches Schließen abgeschlossen. {$closed} Ticket(s) geschlossen (Schwelle: {$days} Tage).";
|
||
|
||
return ['closed' => $closed, 'log' => $log];
|
||
}
|
||
|
||
if (php_sapi_name() === 'cli') {
|
||
$result = run_auto_close_tickets(get_db(), true);
|
||
foreach ($result['log'] as $line) {
|
||
echo $line . "\n";
|
||
}
|
||
}
|