für einen gespeicherten Bericht $in = [ 'dimension' => $_GET['dimension'] ?? null, 'from' => $_GET['from'] ?? null, 'to' => $_GET['to'] ?? null, 'metrics' => array_filter(explode(',', (string) ($_GET['metrics'] ?? ''))), 'sort' => $_GET['sort'] ?? 'label', 'desc' => !empty($_GET['desc']), 'filters' => array_intersect_key($_GET, report_filter_columns()), ]; $savedStmt = $pdo->prepare('SELECT r.*, s.name AS owner FROM saved_reports r LEFT JOIN staff s ON s.id = r.staff_id WHERE r.staff_id = ? OR r.is_shared = 1 ORDER BY r.name'); $savedStmt->execute([$staff['id']]); $saved = $savedStmt->fetchAll(); if (isset($_GET['saved'])) { foreach ($saved as $sr) if ((int) $sr['id'] === (int) $_GET['saved']) $in = json_decode($sr['config'], true) ?: []; } $report = report_run($pdo, $in, staff_department_ids($staff)); api_json([ 'config' => $report['config'], 'columns' => $report['columns'], 'rows' => $report['rows'], 'totals' => $report['totals'], 'dimensions' => array_map(fn($k, $d) => ['key' => $k, 'label' => $d[0]], array_keys(report_dimensions($pdo)), report_dimensions($pdo)), 'metrics' => array_map(fn($k, $m) => ['key' => $k, 'label' => $m[0], 'unit' => $m[2]], array_keys(report_metrics($pdo)), report_metrics($pdo)), 'saved' => array_map(fn($sr) => ['id' => (int) $sr['id'], 'name' => $sr['name'], 'isShared' => (bool) $sr['is_shared'], 'mine' => (int) $sr['staff_id'] === (int) $staff['id'], 'ownerName' => $sr['owner']], $saved), ]); } $body = api_request_body(); $action = $body['action'] ?? ''; if ($action === 'save') { $name = trim((string) ($body['name'] ?? '')); if ($name === '') api_error(422, 'NAME_REQUIRED', 'Bitte einen Namen für den Bericht angeben.'); $cfg = report_clean_config($pdo, (array) ($body['config'] ?? [])); $now = db_now(); $pdo->prepare('INSERT INTO saved_reports (staff_id, name, config, is_shared, created_at, updated_at) VALUES (?,?,?,?,?,?)') ->execute([$staff['id'], mb_substr($name, 0, 120), json_encode($cfg, JSON_UNESCAPED_UNICODE), (!empty($body['isShared']) && has_permission($staff, 'share_views')) ? 1 : 0, $now, $now]); api_json(['id' => (int) $pdo->lastInsertId()]); } if ($action === 'delete') { $stmt = $pdo->prepare('SELECT * FROM saved_reports WHERE id = ?'); $stmt->execute([(int) ($body['id'] ?? 0)]); $row = $stmt->fetch(); if (!$row) api_error(404, 'NOT_FOUND', 'Bericht nicht gefunden.'); if ((int) $row['staff_id'] !== (int) $staff['id'] && $staff['role'] !== 'admin') api_error(403, 'FORBIDDEN', 'Dieser Bericht gehört einem anderen Mitarbeiter.'); $pdo->prepare('DELETE FROM saved_reports WHERE id = ?')->execute([$row['id']]); api_json(['ok' => true]); } api_error(422, 'INVALID_ACTION', 'Unbekannte Aktion.');