diff --git a/DeskHub-Webseite/cron/check_sla.php b/DeskHub-Webseite/cron/check_sla.php index d0387931..19987a0b 100644 --- a/DeskHub-Webseite/cron/check_sla.php +++ b/DeskHub-Webseite/cron/check_sla.php @@ -44,7 +44,7 @@ function run_check_sla(PDO $pdo, bool $verbose = false): array foreach ($overdue as $t) { if (!$t['is_overdue']) { - $pdo->prepare('UPDATE tickets SET is_overdue = 1 WHERE id = ?')->execute([$t['id']]); + $pdo->prepare('UPDATE tickets SET is_overdue = 1, updated_at = updated_at 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'); @@ -65,7 +65,7 @@ function run_check_sla(PDO $pdo, bool $verbose = false): array 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"); + $pdo->exec("UPDATE tickets SET is_overdue = 0, updated_at = updated_at WHERE status IN ('resolved','closed') AND is_overdue = 1"); set_setting('cron_check_sla_last_run', $now); diff --git a/DeskHub-Webseite/database/migrate.php b/DeskHub-Webseite/database/migrate.php index b9401364..7303cc38 100644 --- a/DeskHub-Webseite/database/migrate.php +++ b/DeskHub-Webseite/database/migrate.php @@ -1945,6 +1945,41 @@ function run_migrations(PDO $pdo, bool $verbose = false): array } } + // Indizes für die Übersicht (letzte Aktivität) und die Ticketliste (Sortierung nach letzter Bearbeitung) + if (!isset($done['php_0068_overview_indexes'])) { + try { + $hasIndex = function (string $table, string $name) use ($pdo): bool { + $rows = $pdo->query($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'sqlite' ? "PRAGMA index_list($table)" : "SHOW INDEX FROM $table")->fetchAll(); + foreach ($rows as $r) if ((string) ($r['name'] ?? $r['Key_name'] ?? '') === $name) return true; + return false; + }; + if (!$hasIndex('activity_log', 'idx_activity_log_created')) $pdo->exec('CREATE INDEX idx_activity_log_created ON activity_log (created_at)'); + if (!$hasIndex('tickets', 'idx_tickets_updated')) $pdo->exec('CREATE INDEX idx_tickets_updated ON tickets (updated_at)'); + $pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0068_overview_indexes']); + $result['applied']++; + if ($verbose) $result['log'][] = ' [OK] php_0068_overview_indexes'; + } catch (Throwable $e) { + $result['errors'][] = 'php_0068_overview_indexes: ' . $e->getMessage(); + if ($verbose) $result['log'][] = ' [FAIL] php_0068_overview_indexes - ' . $e->getMessage(); + } + } + + // Statusseite: Dienste lassen sich als „intern“ markieren (werden geprüft, erscheinen aber nicht auf der öffentlichen Statusseite) + if (!isset($done['php_0069_status_component_internal'])) { + try { + $cols = $pdo->query($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) === 'sqlite' ? 'PRAGMA table_info(status_components)' : 'SHOW COLUMNS FROM status_components')->fetchAll(); + $has = false; + foreach ($cols as $col) if (($col['name'] ?? $col['Field'] ?? '') === 'is_internal') $has = true; + if (!$has) $pdo->exec('ALTER TABLE status_components ADD COLUMN is_internal TINYINT NOT NULL DEFAULT 0'); + $pdo->prepare('INSERT INTO schema_migrations (migration) VALUES (?)')->execute(['php_0069_status_component_internal']); + $result['applied']++; + if ($verbose) $result['log'][] = ' [OK] php_0069_status_component_internal'; + } catch (Throwable $e) { + $result['errors'][] = 'php_0069_status_component_internal: ' . $e->getMessage(); + if ($verbose) $result['log'][] = ' [FAIL] php_0069_status_component_internal - ' . $e->getMessage(); + } + } + return $result; }