feat: [settings] AI 토큰사용량 조회 API 추가
- GET /settings/ai-token-usage: 목록 + 통계 조회 - GET /settings/ai-token-usage/pricing: 단가 설정 조회 (읽기 전용) - AiTokenHelper: Gemini/Claude/R2/STT 사용량 기록 헬퍼 - AiPricingConfig 캐시에 cloudflare-r2 provider 추가
This commit is contained in:
72
app/Services/AiTokenUsageService.php
Normal file
72
app/Services/AiTokenUsageService.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Tenants\AiPricingConfig;
|
||||
use App\Models\Tenants\AiTokenUsage;
|
||||
|
||||
class AiTokenUsageService extends Service
|
||||
{
|
||||
/**
|
||||
* 토큰 사용량 목록 + 통계
|
||||
*/
|
||||
public function list(array $params): array
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$query = AiTokenUsage::where('tenant_id', $tenantId)
|
||||
->when($params['start_date'] ?? null, fn ($q, $d) => $q->whereDate('created_at', '>=', $d))
|
||||
->when($params['end_date'] ?? null, fn ($q, $d) => $q->whereDate('created_at', '<=', $d))
|
||||
->when($params['menu_name'] ?? null, fn ($q, $m) => $q->where('menu_name', $m));
|
||||
|
||||
// 통계 (페이지네이션 전 전체 집계)
|
||||
$stats = (clone $query)->selectRaw('
|
||||
COUNT(*) as total_count,
|
||||
COALESCE(SUM(prompt_tokens), 0) as total_prompt_tokens,
|
||||
COALESCE(SUM(completion_tokens), 0) as total_completion_tokens,
|
||||
COALESCE(SUM(total_tokens), 0) as total_total_tokens,
|
||||
COALESCE(SUM(cost_usd), 0) as total_cost_usd,
|
||||
COALESCE(SUM(cost_krw), 0) as total_cost_krw
|
||||
')->first();
|
||||
|
||||
// 목록 (페이지네이션)
|
||||
$items = $query->with('creator:id,name')
|
||||
->orderByDesc('created_at')
|
||||
->paginate($params['per_page'] ?? 20);
|
||||
|
||||
// 메뉴명 필터 옵션
|
||||
$menuNames = AiTokenUsage::where('tenant_id', $tenantId)
|
||||
->select('menu_name')
|
||||
->distinct()
|
||||
->orderBy('menu_name')
|
||||
->pluck('menu_name');
|
||||
|
||||
return [
|
||||
'items' => $items,
|
||||
'stats' => [
|
||||
'total_count' => (int) $stats->total_count,
|
||||
'total_prompt_tokens' => (int) $stats->total_prompt_tokens,
|
||||
'total_completion_tokens' => (int) $stats->total_completion_tokens,
|
||||
'total_total_tokens' => (int) $stats->total_total_tokens,
|
||||
'total_cost_usd' => (float) $stats->total_cost_usd,
|
||||
'total_cost_krw' => (float) $stats->total_cost_krw,
|
||||
],
|
||||
'menu_names' => $menuNames,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 단가 설정 조회 (읽기 전용)
|
||||
*/
|
||||
public function getPricing(): array
|
||||
{
|
||||
$configs = AiPricingConfig::where('is_active', true)
|
||||
->orderBy('provider')
|
||||
->get();
|
||||
|
||||
return [
|
||||
'pricing' => $configs,
|
||||
'exchange_rate' => AiPricingConfig::getExchangeRate(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user