feat:AI 토큰 단가 설정 UI 및 DB 조회 연동

- AiPricingConfig 모델 추가 (캐시 적용 단가/환율 조회)
- AiTokenUsageController에 pricingList/pricingUpdate 메서드 추가
- AI 토큰 사용량 페이지에 설정 버튼 + 모달 UI 추가
- AiTokenHelper 하드코딩 단가를 DB 조회로 변경
- pricing 라우트 추가 (GET/PUT)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
김보곤
2026-02-09 09:33:56 +09:00
parent ab7c3bd494
commit 4ed902e846
5 changed files with 412 additions and 11 deletions

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\System;
use App\Http\Controllers\Controller;
use App\Models\System\AiPricingConfig;
use App\Models\System\AiTokenUsage;
use App\Models\Tenants\Tenant;
use Illuminate\Http\JsonResponse;
@@ -120,4 +121,57 @@ public function list(Request $request): JsonResponse
],
]);
}
public function pricingList(): JsonResponse
{
$configs = AiPricingConfig::orderBy('id')->get();
return response()->json([
'success' => true,
'data' => $configs->map(fn ($c) => [
'id' => $c->id,
'provider' => $c->provider,
'model_name' => $c->model_name,
'input_price_per_million' => (float) $c->input_price_per_million,
'output_price_per_million' => (float) $c->output_price_per_million,
'unit_price' => (float) $c->unit_price,
'unit_description' => $c->unit_description,
'exchange_rate' => (float) $c->exchange_rate,
'is_active' => $c->is_active,
'description' => $c->description,
]),
]);
}
public function pricingUpdate(Request $request): JsonResponse
{
$validated = $request->validate([
'configs' => 'required|array',
'configs.*.id' => 'required|integer|exists:ai_pricing_configs,id',
'configs.*.model_name' => 'required|string|max:100',
'configs.*.input_price_per_million' => 'required|numeric|min:0',
'configs.*.output_price_per_million' => 'required|numeric|min:0',
'configs.*.unit_price' => 'required|numeric|min:0',
'configs.*.exchange_rate' => 'required|numeric|min:0',
'configs.*.description' => 'nullable|string|max:255',
]);
foreach ($validated['configs'] as $item) {
AiPricingConfig::where('id', $item['id'])->update([
'model_name' => $item['model_name'],
'input_price_per_million' => $item['input_price_per_million'],
'output_price_per_million' => $item['output_price_per_million'],
'unit_price' => $item['unit_price'],
'exchange_rate' => $item['exchange_rate'],
'description' => $item['description'] ?? null,
]);
}
AiPricingConfig::clearCache();
return response()->json([
'success' => true,
'message' => '단가 설정이 저장되었습니다.',
]);
}
}