Files
sam-manage/app/Http/Controllers/System/AiTokenUsageController.php

124 lines
4.3 KiB
PHP
Raw Normal View History

<?php
namespace App\Http\Controllers\System;
use App\Http\Controllers\Controller;
use App\Models\System\AiTokenUsage;
use App\Models\Tenants\Tenant;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;
class AiTokenUsageController extends Controller
{
public function index(Request $request): View|Response
{
if ($request->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(),
],
]);
}
}