Upload via GUI (258 Dateien)

This commit is contained in:
2026-10-16 19:12:24 +00:00
parent de06066052
commit 5a602de484
50 changed files with 8948 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
<?php
require_once __DIR__ . '/../includes/bootstrap.php';
$staff = require_staff_login();
$pdo = get_db();
$ticketId = (int)($_GET['id'] ?? 0);
if (!$ticketId) redirect('/staff/tickets.php');
$stmt = $pdo->prepare(
'SELECT t.*, d.name AS department_name, p.name AS priority_name
FROM tickets t
JOIN departments d ON d.id = t.department_id
JOIN priorities p ON p.id = t.priority_id
WHERE t.id = ?'
);
$stmt->execute([$ticketId]);
$ticket = $stmt->fetch();
if (!$ticket) { http_response_code(404); die('Ticket nicht gefunden.'); }
if (!staff_can_access_department($staff, (int) $ticket['department_id'])) { http_response_code(403); die('Sie haben keinen Zugriff auf Tickets dieser Abteilung.'); }
// Nachrichten laden
$threads = $pdo->prepare(
'SELECT tt.*, s.name AS staff_name
FROM ticket_threads tt
LEFT JOIN staff s ON s.id = tt.staff_id
WHERE tt.ticket_id = ? AND tt.is_internal_note = 0
ORDER BY tt.created_at ASC'
);
$threads->execute([$ticketId]);
$messages = $threads->fetchAll();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$selectedMsgIds = array_map('intval', $_POST['message_ids'] ?? []);
$newSubject = trim($_POST['new_subject'] ?? '');
if (empty($selectedMsgIds)) {
$errors[] = 'Bitte mindestens eine Nachricht auswählen.';
} elseif (!$newSubject) {
$errors[] = 'Bitte einen Betreff für das neue Ticket angeben.';
} else {
// Neues Ticket erstellen
$newNumber = generate_ticket_number();
$pdo->prepare(
'INSERT INTO tickets (ticket_number, subject, status, priority_id, department_id,
user_id, requester_name, requester_email, source, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?)'
)->execute([
$newNumber, $newSubject, 'open',
$ticket['priority_id'], $ticket['department_id'],
$ticket['user_id'], $ticket['requester_name'], $ticket['requester_email'],
'staff', db_now(), db_now()
]);
$newId = $pdo->lastInsertId();
// Ausgewählte Nachrichten verschieben
$moved = 0;
foreach ($selectedMsgIds as $msgId) {
$rows = $pdo->prepare('UPDATE ticket_threads SET ticket_id=? WHERE id=? AND ticket_id=?');
$rows->execute([$newId, $msgId, $ticketId]);
$moved += $rows->rowCount();
}
// Anhänge der verschobenen Nachrichten mitnehmen
if ($moved > 0) {
$placeholders = implode(',', array_fill(0, count($selectedMsgIds), '?'));
$pdo->prepare("UPDATE ticket_attachments SET ticket_id=? WHERE thread_id IN ($placeholders)")
->execute(array_merge([$newId], $selectedMsgIds));
}
// Log-Einträge
log_activity($pdo, $ticketId, $staff['id'], "Ticket aufgeteilt → #{$newNumber} ({$moved} Nachrichten)");
log_activity($pdo, $newId, $staff['id'], "Erstellt durch Aufteilen von #{$ticket['ticket_number']}");
audit_log($staff['id'], "Ticket #{$ticket['ticket_number']} aufgeteilt → #{$newNumber}");
flash('success', "Ticket aufgeteilt. Neues Ticket: #{$newNumber}");
redirect('/staff/ticket_view.php?n=' . urlencode($newNumber));
}
}
$pageTitle = 'Ticket aufteilen';
$activePage = 'tickets';
require __DIR__ . '/_header.php';
?>
<div class="topbar">
<div>
<h1>Ticket aufteilen</h1>
<span class="ticket-no">#<?= e($ticket['ticket_number']) ?></span>
</div>
<a href="/staff/ticket_view.php?n=<?= urlencode($ticket['ticket_number']) ?>" class="btn secondary">← Zurück</a>
</div>
<?php foreach ($errors as $err): ?><div class="flash error"><?= e($err) ?></div><?php endforeach; ?>
<div style="display:grid; grid-template-columns:2fr 1fr; gap:20px; align-items:start">
<div class="card">
<h3>Nachrichten auswählen</h3>
<p class="muted" style="font-size:.85rem; margin-bottom:16px">
Wähle die Nachrichten aus die in das neue Ticket verschoben werden sollen. Die gewählten Nachrichten werden aus diesem Ticket entfernt.
</p>
<form method="post" id="split-form">
<?= csrf_field() ?>
<div style="display:flex; flex-direction:column; gap:10px; margin-bottom:20px">
<?php foreach ($messages as $msg): ?>
<label style="display:flex; gap:12px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer; transition:background .12s"
onmouseover="this.style.background='var(--bg-soft)'" onmouseout="this.style.background=''">
<input type="checkbox" name="message_ids[]" value="<?= $msg['id'] ?>"
style="width:auto; margin-top:3px; flex-shrink:0">
<div style="min-width:0; flex:1">
<div style="display:flex; justify-content:space-between; margin-bottom:4px">
<strong style="font-size:.83rem"><?= e($msg['staff_name'] ?? $ticket['requester_name']) ?></strong>
<span class="muted" style="font-size:.75rem"><?= format_dt($msg['created_at']) ?></span>
</div>
<div style="font-size:.85rem; color:var(--ink-soft); white-space:nowrap; overflow:hidden; text-overflow:ellipsis">
<?= e(mb_substr(strip_tags($msg['message']), 0, 120)) ?>
</div>
</div>
</label>
<?php endforeach; ?>
</div>
<label>Betreff des neuen Tickets</label>
<input type="text" name="new_subject" value="<?= e('Re: '.$ticket['subject']) ?>" required>
<div class="btn-row" style="margin-top:16px">
<button type="submit" class="btn" onclick="return confirm('Ausgewählte Nachrichten in neues Ticket verschieben?')">
✂️ Ticket aufteilen
</button>
</div>
</form>
</div>
<div class="card">
<h3>Hinweise</h3>
<ul style="padding-left:20px; line-height:2; font-size:.85rem; color:var(--muted)">
<li>Ausgewählte Nachrichten werden in ein <strong style="color:var(--ink)">neues Ticket</strong> verschoben</li>
<li>Anhänge der Nachrichten werden mitgenommen</li>
<li>Das ursprüngliche Ticket bleibt mit den verbleibenden Nachrichten erhalten</li>
<li>Beide Tickets erhalten einen Log-Eintrag</li>
</ul>
<div style="background:var(--bg-soft); border-radius:8px; padding:14px; margin-top:16px; font-size:.83rem">
<div class="muted" style="margin-bottom:6px">Ursprüngliches Ticket</div>
<strong>#<?= e($ticket['ticket_number']) ?></strong> – <?= e($ticket['subject']) ?>
<div class="muted" style="margin-top:4px"><?= count($messages) ?> Nachrichten gesamt</div>
</div>
</div>
</div>
<?php require __DIR__ . '/_footer.php'; ?>