get('per_page', 20), 200); $filters = $request->only([ 'log_name', 'event', 'causer_type', 'causer_id', 'causer_name', 'subject_type', 'subject_id', 'ip_address', 'date_from', 'date_to', 'search', 'page', ]); $cacheKey = CacheKey::build('activity_logs', 'list', array_merge( $filters, [ 'per_page' => $perPage, 'page' => (int) $request->get('page', 1), 'version' => $this->cacheVersion(), ] )); $data = Cache::remember($cacheKey, self::CACHE_TTL, function () use ($filters, $perPage) { $paginator = $this->activityLogRepository->filter($filters, $perPage); return [ 'items' => $paginator->items(), 'total' => $paginator->total(), 'per_page' => $paginator->perPage(), 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), ]; }); return response()->json(['error' => false, 'data' => $data]); } public function show(int $id): JsonResponse { $cacheKey = CacheKey::build('activity_logs', 'detail', [ 'id' => $id, 'version' => $this->cacheVersion(), ]); $log = Cache::remember($cacheKey, self::CACHE_TTL * 5, function () use ($id) { return $this->activityLogRepository->find($id); }); if (!$log) { return response()->json(['error' => true, 'message' => 'Không tìm thấy log'], 404); } return response()->json(['error' => false, 'data' => $log]); } public function modules(): JsonResponse { $cacheKey = CacheKey::build('activity_logs', 'modules', ['version' => $this->cacheVersion()]); $modules = Cache::remember($cacheKey, self::CACHE_TTL * 10, function () { return ActivityLog::query() ->select('log_name') ->distinct() ->orderBy('log_name') ->pluck('log_name'); }); return response()->json(['error' => false, 'data' => $modules]); } public function stats(): JsonResponse { $cacheKey = CacheKey::build('activity_logs', 'stats', ['version' => $this->cacheVersion()]); $stats = Cache::remember($cacheKey, self::CACHE_TTL * 2, function () { return [ 'total' => ActivityLog::count(), 'today' => ActivityLog::whereDate('created_at', today())->count(), 'by_event' => ActivityLog::selectRaw('event, COUNT(*) as count') ->groupBy('event') ->orderByDesc('count') ->limit(10) ->pluck('count', 'event'), 'by_causer' => ActivityLog::selectRaw('causer_type, COUNT(*) as count') ->groupBy('causer_type') ->pluck('count', 'causer_type'), ]; }); return response()->json(['error' => false, 'data' => $stats]); } public function export(Request $request, BrandedReportWriter $writer): BinaryFileResponse { $filters = $request->validate($this->filterRules()); $query = $this->activityLogRepository->query(array_filter( $filters, fn ($value) => $value !== null && $value !== '', )); return $writer->download( new ActivityLogsExport($query), 'lich-su-hoat-dong-' . now()->format('Y-m-d-His') . '.xlsx', ); } public function destroy(Request $request): JsonResponse { $validated = $request->validate([ 'mode' => ['required', 'string', 'in:all,date_range'], 'date_from' => ['required_if:mode,date_range', 'nullable', 'date_format:Y-m-d'], 'date_to' => ['required_if:mode,date_range', 'nullable', 'date_format:Y-m-d', 'after_or_equal:date_from'], ]); $query = ActivityLog::query(); if ($validated['mode'] === 'date_range') { $query ->where('created_at', '>=', $validated['date_from'] . ' 00:00:00') ->where('created_at', '<=', $validated['date_to'] . ' 23:59:59'); } $deleted = $query->delete(); Cache::forever('activity_logs:version', $this->cacheVersion() + 1); return response()->json([ 'error' => false, 'message' => "Đã xóa {$deleted} log hoạt động.", 'data' => ['deleted' => $deleted], ]); } private function filterRules(): array { return [ 'log_name' => ['nullable', 'string', 'max:100'], 'event' => ['nullable', 'string', 'max:100'], 'causer_type' => ['nullable', 'string', 'max:100'], 'causer_id' => ['nullable', 'integer'], 'causer_name' => ['nullable', 'string', 'max:255'], 'subject_type' => ['nullable', 'string', 'max:255'], 'subject_id' => ['nullable', 'string', 'max:255'], 'ip_address' => ['nullable', 'ip'], 'date_from' => ['nullable', 'date_format:Y-m-d'], 'date_to' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:date_from'], 'search' => ['nullable', 'string', 'max:255'], ]; } private function cacheVersion(): int { return (int) Cache::get('activity_logs:version', 1); } }