141 lines
6.9 KiB
PHP
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.');
|