feat: log IA con filtro por mes y costo por petición + fix promos sin tarifaPromo

- ShowAiLogs: filtro rápido por mes (YYYY-MM) mutuamente excluyente con rango de fechas
- Resumen IA: nueva card Costo Gemini y Costo Total (Gemini + Whisper)
- Tabla IA: columna Costo COP calcula (tokens/1M × $20.000) para Gemini, costo guardado para Whisper
- PublicChat + TelegramBotService: quita whereHas('tarifaPromo') que ocultaba promos sin tarifa por rol

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro
2026-07-19 21:08:40 +00:00
co-authored by Claude Sonnet 4.6
parent 343baa9c14
commit 5c7c8c8a95
4 changed files with 101 additions and 38 deletions
+44 -18
View File
@@ -6,7 +6,12 @@
</div>
{{-- Cards resumen --}}
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
@php
$costoGemini = $resumen->costo_gemini ?? 0;
$costoWhisper = $resumen->costo_whisper ?? 0;
$costoTotal = $costoGemini + $costoWhisper;
@endphp
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-4">
<div class="bg-white rounded-2xl border border-gray-100 shadow p-4">
<p class="text-xs text-gray-400 mb-1">Total llamadas</p>
<p class="text-2xl font-bold text-gray-800">{{ number_format($resumen->total_llamadas ?? 0) }}</p>
@@ -20,7 +25,7 @@
<p class="text-xs text-gray-400 mb-1">Tokens Gemini</p>
<p class="text-2xl font-bold text-blue-700">{{ number_format(($resumen->total_input_tokens ?? 0) + ($resumen->total_output_tokens ?? 0)) }}</p>
<p class="text-xs text-gray-400 mt-1">
Entrada: {{ number_format($resumen->total_input_tokens ?? 0) }} · Salida: {{ number_format($resumen->total_output_tokens ?? 0) }}
E: {{ number_format($resumen->total_input_tokens ?? 0) }} · S: {{ number_format($resumen->total_output_tokens ?? 0) }}
</p>
</div>
<div class="bg-white rounded-2xl border border-gray-100 shadow p-4">
@@ -29,15 +34,41 @@
<p class="text-xs text-gray-400 mt-1">segundos transcritos</p>
</div>
<div class="bg-white rounded-2xl border border-gray-100 shadow p-4">
<p class="text-xs text-gray-400 mb-1">Costo Whisper</p>
<p class="text-2xl font-bold text-emerald-700">${{ number_format($resumen->costo_whisper ?? 0) }}</p>
<p class="text-xs text-gray-400 mt-1">$1 por segundo · Tiempo prom: {{ number_format($resumen->avg_tiempo_ms ?? 0) }}ms</p>
<p class="text-xs text-gray-400 mb-1">Costo Gemini</p>
<p class="text-2xl font-bold text-blue-700">${{ number_format($costoGemini, 0, ',', '.') }}</p>
<p class="text-xs text-gray-400 mt-1">$20.000 / millón tokens</p>
</div>
<div class="bg-white rounded-2xl border border-gray-100 shadow p-4">
<p class="text-xs text-gray-400 mb-1">Costo Total</p>
<p class="text-2xl font-bold text-emerald-700">${{ number_format($costoTotal, 0, ',', '.') }}</p>
<p class="text-xs text-gray-400 mt-1">
Whisper: ${{ number_format($costoWhisper, 0, ',', '.') }}
· Prom: {{ number_format($resumen->avg_tiempo_ms ?? 0) }}ms
</p>
</div>
</div>
{{-- Filtros --}}
<div class="bg-white rounded-2xl border border-gray-100 shadow p-4">
<div class="flex flex-wrap gap-3 items-end">
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Mes</label>
<select wire:model.live="filtroMes" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-emerald-500 outline-none">
<option value="">Todos los meses</option>
@foreach($meses as $mes)
<option value="{{ $mes['value'] }}">{{ $mes['label'] }}</option>
@endforeach
</select>
</div>
<div class="flex items-end gap-1 pb-2 text-gray-400 text-xs">ó rango:</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Desde</label>
<input wire:model.live="filtroFechaDesde" type="date" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-emerald-500 outline-none">
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Hasta</label>
<input wire:model.live="filtroFechaHasta" type="date" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-emerald-500 outline-none">
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Servicio</label>
<select wire:model.live="filtroServicio" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-emerald-500 outline-none">
@@ -55,15 +86,7 @@
<option value="telegram">Telegram</option>
</select>
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Desde</label>
<input wire:model.live="filtroFechaDesde" type="date" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-emerald-500 outline-none">
</div>
<div>
<label class="block text-xs font-semibold text-gray-600 mb-1">Hasta</label>
<input wire:model.live="filtroFechaHasta" type="date" class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-emerald-500 outline-none">
</div>
<button wire:click="$set('filtroServicio','');$set('filtroCanal','');$set('filtroFechaDesde','');$set('filtroFechaHasta','')"
<button wire:click="$set('filtroServicio','');$set('filtroCanal','');$set('filtroFechaDesde','');$set('filtroFechaHasta','');$set('filtroMes','')"
class="px-4 py-2 text-sm border border-gray-300 rounded-lg hover:bg-gray-50 text-gray-600">
Limpiar
</button>
@@ -83,7 +106,7 @@
<th class="text-right px-4 py-3 text-xs font-semibold text-gray-500">Tokens E/S</th>
<th class="text-right px-4 py-3 text-xs font-semibold text-gray-500">Audio</th>
<th class="text-right px-4 py-3 text-xs font-semibold text-gray-500">Tiempo</th>
<th class="text-right px-4 py-3 text-xs font-semibold text-gray-500">Costo</th>
<th class="text-right px-4 py-3 text-xs font-semibold text-gray-500">Costo COP</th>
<th class="text-center px-4 py-3 text-xs font-semibold text-gray-500">Estado</th>
<th class="text-left px-4 py-3 text-xs font-semibold text-gray-500">Detalle</th>
</tr>
@@ -104,6 +127,9 @@
'whisper' => 'Whisper',
default => $log->servicio,
};
$costoFila = in_array($log->servicio, ['gemini_intent', 'gemini_vision'])
? (($log->input_tokens ?? 0) + ($log->output_tokens ?? 0)) / 1000000 * 20000
: ($log->costo ?? 0);
@endphp
<tr class="hover:bg-gray-50/50">
<td class="px-4 py-3 text-gray-500 whitespace-nowrap text-xs">
@@ -132,9 +158,9 @@
@endif
</td>
<td class="px-4 py-3 text-right text-xs text-gray-600">{{ number_format($log->tiempo_ms) }}ms</td>
<td class="px-4 py-3 text-right text-xs font-semibold {{ $log->costo > 0 ? 'text-emerald-700' : 'text-gray-400' }}">
@if($log->costo > 0)
${{ number_format($log->costo) }}
<td class="px-4 py-3 text-right text-xs font-semibold {{ $costoFila > 0 ? 'text-emerald-700' : 'text-gray-400' }}">
@if($costoFila > 0)
${{ number_format($costoFila, 0, ',', '.') }}
@else
@endif