header('HX-Request')) { return response('', 200)->header('HX-Redirect', route('system.ai-token-usage.index')); } return view('system.ai-token-usage.index'); } public function list(Request $request): JsonResponse { $perPage = $request->input('per_page', 20); $startDate = $request->input('start_date'); $endDate = $request->input('end_date'); $tenantId = $request->input('tenant_id'); $menuName = $request->input('menu_name'); $query = AiTokenUsage::query() ->orderByDesc('created_at'); if ($tenantId) { $query->where('tenant_id', $tenantId); } if ($menuName) { $query->where('menu_name', $menuName); } if ($startDate) { $query->whereDate('created_at', '>=', $startDate); } if ($endDate) { $query->whereDate('created_at', '<=', $endDate); } // 통계 (필터 조건 동일하게 적용) $statsQuery = clone $query; $stats = $statsQuery->selectRaw(' COUNT(*) as total_count, SUM(prompt_tokens) as total_prompt_tokens, SUM(completion_tokens) as total_completion_tokens, SUM(total_tokens) as total_total_tokens, SUM(cost_usd) as total_cost_usd, SUM(cost_krw) as total_cost_krw ')->first(); // 페이지네이션 $records = $query->paginate($perPage); // 테넌트 이름 매핑 $tenantIds = $records->pluck('tenant_id')->unique(); $tenants = Tenant::whereIn('id', $tenantIds)->pluck('company_name', 'id'); $data = $records->through(function ($item) use ($tenants) { return [ 'id' => $item->id, 'tenant_id' => $item->tenant_id, 'tenant_name' => $tenants[$item->tenant_id] ?? '-', 'model' => $item->model, 'menu_name' => $item->menu_name, 'prompt_tokens' => $item->prompt_tokens, 'completion_tokens' => $item->completion_tokens, 'total_tokens' => $item->total_tokens, 'cost_usd' => (float) $item->cost_usd, 'cost_krw' => (float) $item->cost_krw, 'request_id' => $item->request_id, 'created_at' => $item->created_at->format('Y-m-d H:i:s'), ]; }); // 필터용 메뉴 목록 $menuNames = AiTokenUsage::select('menu_name') ->distinct() ->orderBy('menu_name') ->pluck('menu_name'); // 필터용 테넌트 목록 $allTenantIds = AiTokenUsage::select('tenant_id') ->distinct() ->pluck('tenant_id'); $allTenants = Tenant::whereIn('id', $allTenantIds) ->orderBy('company_name') ->get(['id', 'company_name']); return response()->json([ 'success' => true, 'data' => $data->items(), 'stats' => [ 'total_count' => (int) ($stats->total_count ?? 0), 'total_prompt_tokens' => (int) ($stats->total_prompt_tokens ?? 0), 'total_completion_tokens' => (int) ($stats->total_completion_tokens ?? 0), 'total_total_tokens' => (int) ($stats->total_total_tokens ?? 0), 'total_cost_usd' => round((float) ($stats->total_cost_usd ?? 0), 6), 'total_cost_krw' => round((float) ($stats->total_cost_krw ?? 0), 2), ], 'filters' => [ 'menu_names' => $menuNames, 'tenants' => $allTenants->map(fn ($t) => ['id' => $t->id, 'name' => $t->company_name]), ], 'pagination' => [ 'current_page' => $records->currentPage(), 'last_page' => $records->lastPage(), 'per_page' => $records->perPage(), 'total' => $records->total(), ], ]); } }