Files
2026-10-16 19:12:13 +00:00

109 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/common.php';
api_require_method('POST');
$staff = api_require_staff();
api_require_permission($staff, 'create_ticket');
$pdo = get_db();
$body = api_request_body();
$requesterName = trim((string) ($body['requesterName'] ?? ''));
$requesterEmail = trim((string) ($body['requesterEmail'] ?? ''));
$subject = trim((string) ($body['subject'] ?? ''));
$message = sanitize_staff_html(trim((string) ($body['message'] ?? '')));
$departmentId = (int) ($body['departmentId'] ?? 0);
$priorityId = (int) ($body['priorityId'] ?? 0);
$assignedStaffId = ($body['assignedStaffId'] ?? null) !== null ? (int) $body['assignedStaffId'] : null;
$notifyCustomer = !empty($body['notifyCustomer']);
if ($requesterName === '') {
api_error(422, 'REQUESTER_NAME_REQUIRED', 'Bitte einen Namen angeben.');
}
if ($requesterEmail !== '' && !filter_var($requesterEmail, FILTER_VALIDATE_EMAIL)) {
api_error(422, 'INVALID_EMAIL', 'Bitte eine gültige E-Mail-Adresse angeben (oder leer lassen).');
}
if ($subject === '') {
api_error(422, 'SUBJECT_REQUIRED', 'Bitte einen Betreff angeben.');
}
if (trim(strip_tags($message)) === '') {
api_error(422, 'MESSAGE_REQUIRED', 'Bitte eine Beschreibung eingeben.');
}
if ($requesterEmail !== '' && is_banned($requesterEmail)) {
api_error(403, 'REQUESTER_BANNED', 'Diese E-Mail-Adresse steht auf der Sperrliste.');
}
$departmentIds = staff_department_ids($staff);
if ($departmentIds !== null && !in_array($departmentId, $departmentIds, true)) {
api_error(403, 'DEPARTMENT_FORBIDDEN', 'Auf diese Abteilung besteht kein Zugriff.');
}
$deptStmt = $pdo->prepare('SELECT * FROM departments WHERE id = ?');
$deptStmt->execute([$departmentId]);
$department = $deptStmt->fetch();
if ($department && empty($department['is_active'])) {
api_error(422, 'DEPARTMENT_INACTIVE', 'Diese Abteilung ist deaktiviert. Bitte eine aktive Abteilung wählen.');
}
if (!$department) {
api_error(422, 'INVALID_DEPARTMENT', 'Die Abteilung ist ungültig.');
}
$prioStmt = $pdo->prepare('SELECT * FROM priorities WHERE id = ?');
$prioStmt->execute([$priorityId]);
$priority = $prioStmt->fetch();
if (!$priority) {
api_error(422, 'INVALID_PRIORITY', 'Die Priorität ist ungültig.');
}
$sla = calc_sla_dates($priority, null, (int) $departmentId, null);
$now = db_now();
$ticketNumber = generate_ticket_number($pdo);
$userId = null;
if ($requesterEmail !== '') {
$userStmt = $pdo->prepare('SELECT id FROM users WHERE LOWER(email) = LOWER(?)');
$userStmt->execute([$requesterEmail]);
$userId = $userStmt->fetchColumn() ?: null;
}
$pdo->beginTransaction();
try {
$pdo->prepare(
'INSERT INTO tickets (ticket_number, subject, user_id, requester_name, requester_email, department_id,
priority_id, status, source, assigned_staff_id,
first_response_due_at, resolution_due_at, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)'
)->execute([
$ticketNumber, $subject, $userId, $requesterName, $requesterEmail, $departmentId,
$priorityId, 'open', 'staff', $assignedStaffId,
$sla['first_response_due_at'], $sla['resolution_due_at'], $now, $now,
]);
$ticketId = (int) $pdo->lastInsertId();
$pdo->prepare(
'INSERT INTO ticket_threads (ticket_id, author_type, staff_id, message, is_internal_note, created_at)
VALUES (?,?,?,?,0,?)'
)->execute([$ticketId, 'staff', $staff['id'], $message, $now]);
log_activity($pdo, $ticketId, (int) $staff['id'], 'Ticket durch Mitarbeiter erstellt (Mobile App)');
$pdo->commit();
} catch (Throwable $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
throw $e;
}
if ($requesterEmail !== '' && $notifyCustomer) {
notify_customer_ticket_created([
'ticket_number' => $ticketNumber,
'subject' => $subject,
'requester_name' => $requesterName,
'requester_email' => $requesterEmail,
'department_id' => $departmentId,
'department_name' => $department['name'],
]);
}
$ticket = api_find_ticket($pdo, $staff, $ticketNumber);
webhook_dispatch($pdo, 'ticket.created', (int) $ticket['id']);
api_json(['ticket' => api_ticket_summary($ticket)], 201);