Files
deskhub/DeskHub-Webseite/api/staff/v1/escalation_rules.php
T
2026-10-16 19:12:13 +00:00

141 lines
6.9 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/common.php';
api_require_method('GET', 'POST');
$staff = api_require_staff();
api_require_admin_or_permission($staff, 'manage_escalations');
$pdo = get_db();
const ESCALATION_TRIGGER_TYPES = ['no_reply', 'no_update', 'overdue', 'open_too_long'];
const ESCALATION_SET_STATUSES = ['open', 'pending', 'on_hold'];
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$priorities = $pdo->query('SELECT id, name FROM priorities ORDER BY sort_order')->fetchAll();
$staffList = $pdo->query('SELECT id, name FROM staff WHERE is_active = 1 ORDER BY name')->fetchAll();
$depts = $pdo->query('SELECT id, name FROM departments ORDER BY name')->fetchAll();
try {
$rules = $pdo->query(
'SELECT er.*,
p.name AS prio_name,
s.name AS staff_name,
d.name AS dept_name,
cp.name AS cond_prio_name,
(SELECT COUNT(*) FROM escalation_log el WHERE el.rule_id = er.id) AS applied_count
FROM escalation_rules er
LEFT JOIN priorities p ON p.id = er.action_set_priority_id
LEFT JOIN staff s ON s.id = er.action_assign_staff_id
LEFT JOIN departments d ON d.id = er.condition_dept_id
LEFT JOIN priorities cp ON cp.id = er.condition_priority_id
ORDER BY er.sort_order, er.id'
)->fetchAll();
} catch (Throwable $e) {
$rules = [];
}
api_json([
'priorities' => array_map(fn(array $p) => ['id' => (int) $p['id'], 'name' => $p['name']], $priorities),
'staffOptions' => array_map(fn(array $s) => ['id' => (int) $s['id'], 'name' => $s['name']], $staffList),
'departments' => array_map(fn(array $d) => ['id' => (int) $d['id'], 'name' => $d['name']], $depts),
'rules' => array_map(fn(array $r) => [
'id' => (int) $r['id'],
'name' => $r['name'],
'isActive' => (bool) $r['is_active'],
'triggerType' => $r['trigger_type'],
'triggerHours' => (int) $r['trigger_hours'],
'conditionStatus' => $r['condition_status'],
'conditionPriorityId' => $r['condition_priority_id'] !== null ? (int) $r['condition_priority_id'] : null,
'conditionPriorityName' => $r['cond_prio_name'],
'conditionDeptId' => $r['condition_dept_id'] !== null ? (int) $r['condition_dept_id'] : null,
'conditionDeptName' => $r['dept_name'],
'actionSetPriorityId' => $r['action_set_priority_id'] !== null ? (int) $r['action_set_priority_id'] : null,
'actionSetPriorityName' => $r['prio_name'],
'actionAssignStaffId' => $r['action_assign_staff_id'] !== null ? (int) $r['action_assign_staff_id'] : null,
'actionAssignStaffName' => $r['staff_name'],
'actionSetStatus' => $r['action_set_status'],
'actionNotifyAdmin' => (bool) $r['action_notify_admin'],
'actionNotifyStaff' => (bool) $r['action_notify_staff'],
'sortOrder' => (int) $r['sort_order'],
'appliedCount' => (int) $r['applied_count'],
], $rules),
]);
}
$body = api_request_body();
$action = $body['action'] ?? '';
if ($action === 'toggle') {
$id = (int) ($body['id'] ?? 0);
$pdo->prepare('UPDATE escalation_rules SET is_active = 1 - is_active WHERE id = ?')->execute([$id]);
api_json(['ok' => true]);
}
if ($action === 'delete') {
$id = (int) ($body['id'] ?? 0);
$pdo->prepare('DELETE FROM escalation_rules WHERE id = ?')->execute([$id]);
$pdo->prepare('DELETE FROM escalation_log WHERE rule_id = ?')->execute([$id]);
audit_log($staff['id'], "Eskalationsregel gelöscht: #$id (Mobile App)");
api_json(['ok' => true]);
}
if ($action === 'save') {
$id = (int) ($body['id'] ?? 0);
$name = trim((string) ($body['name'] ?? ''));
$isActive = !empty($body['isActive']) ? 1 : 0;
$triggerType = (string) ($body['triggerType'] ?? 'no_reply');
$triggerHours = max(1, (int) ($body['triggerHours'] ?? 24));
$condStatus = trim((string) ($body['conditionStatus'] ?? ''));
$condPrioId = isset($body['conditionPriorityId']) && $body['conditionPriorityId'] !== null ? (int) $body['conditionPriorityId'] : null;
$condDeptId = isset($body['conditionDeptId']) && $body['conditionDeptId'] !== null ? (int) $body['conditionDeptId'] : null;
$actPrioId = isset($body['actionSetPriorityId']) && $body['actionSetPriorityId'] !== null ? (int) $body['actionSetPriorityId'] : null;
$actStaffId = isset($body['actionAssignStaffId']) && $body['actionAssignStaffId'] !== null ? (int) $body['actionAssignStaffId'] : null;
$actStatus = (string) ($body['actionSetStatus'] ?? '');
$actNotAdmin = !empty($body['actionNotifyAdmin']) ? 1 : 0;
$actNotStaff = !empty($body['actionNotifyStaff']) ? 1 : 0;
$sortOrder = (int) ($body['sortOrder'] ?? 0);
if ($name === '') {
api_error(422, 'NAME_REQUIRED', 'Bitte einen Namen angeben.');
}
if (!in_array($triggerType, ESCALATION_TRIGGER_TYPES, true)) {
api_error(422, 'INVALID_TRIGGER', 'Ungültiger Trigger.');
}
if ($actStatus !== '' && !in_array($actStatus, ESCALATION_SET_STATUSES, true)) {
api_error(422, 'INVALID_STATUS', 'Ungültiger Zielstatus.');
}
$data = [$name, $isActive, $triggerType, $triggerHours, $condStatus ?: null,
$condPrioId, $condDeptId, $actPrioId, $actStaffId,
$actStatus ?: null, $actNotAdmin, $actNotStaff, $sortOrder];
if ($id) {
$existsStmt = $pdo->prepare('SELECT COUNT(*) FROM escalation_rules WHERE id = ?');
$existsStmt->execute([$id]);
if (!(bool) $existsStmt->fetchColumn()) {
api_error(404, 'RULE_NOT_FOUND', 'Die Regel wurde nicht gefunden.');
}
$pdo->prepare(
'UPDATE escalation_rules SET name=?,is_active=?,trigger_type=?,trigger_hours=?,
condition_status=?,condition_priority_id=?,condition_dept_id=?,
action_set_priority_id=?,action_assign_staff_id=?,action_set_status=?,
action_notify_admin=?,action_notify_staff=?,sort_order=? WHERE id=?'
)->execute(array_merge($data, [$id]));
audit_log($staff['id'], "Eskalationsregel geändert: $name (Mobile App)");
$newId = $id;
} else {
$pdo->prepare(
'INSERT INTO escalation_rules (name,is_active,trigger_type,trigger_hours,
condition_status,condition_priority_id,condition_dept_id,
action_set_priority_id,action_assign_staff_id,action_set_status,
action_notify_admin,action_notify_staff,sort_order,created_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)'
)->execute(array_merge($data, [db_now()]));
$newId = (int) $pdo->lastInsertId();
audit_log($staff['id'], "Eskalationsregel erstellt: $name (Mobile App)");
}
api_json(['id' => $newId]);
}
api_error(422, 'INVALID_ACTION', 'Unbekannte Aktion.');