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:
co-authored by
Claude Sonnet 4.6
parent
343baa9c14
commit
5c7c8c8a95
@@ -906,7 +906,6 @@ class PublicChat extends Component
|
||||
|
||||
$promos = Promociones::where('visible', 'true')
|
||||
->where(fn ($q) => $q->whereNull('fecha_limite')->orWhere('fecha_limite', '>=', now()))
|
||||
->whereHas('tarifaPromo', fn ($q) => $q->where('rol_id', $rolId))
|
||||
->with(['tarifaPromo' => fn ($q) => $q->where('rol_id', $rolId)])
|
||||
->get();
|
||||
|
||||
|
||||
Regular → Executable
+57
-18
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Livewire\Chat;
|
||||
|
||||
use App\Models\AiUsageLog;
|
||||
use Carbon\Carbon;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
@@ -10,43 +11,72 @@ class ShowAiLogs extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
public string $filtroServicio = '';
|
||||
public string $filtroCanal = '';
|
||||
public string $filtroServicio = '';
|
||||
public string $filtroCanal = '';
|
||||
public string $filtroFechaDesde = '';
|
||||
public string $filtroFechaHasta = '';
|
||||
public string $filtroMes = '';
|
||||
|
||||
protected $queryString = ['filtroServicio', 'filtroCanal', 'filtroFechaDesde', 'filtroFechaHasta'];
|
||||
protected $queryString = [
|
||||
'filtroServicio', 'filtroCanal',
|
||||
'filtroFechaDesde', 'filtroFechaHasta',
|
||||
'filtroMes',
|
||||
];
|
||||
|
||||
public function updatingFiltroServicio(): void { $this->resetPage(); }
|
||||
public function updatingFiltroCanal(): void { $this->resetPage(); }
|
||||
public function updatingFiltroServicio(): void { $this->resetPage(); }
|
||||
public function updatingFiltroCanal(): void { $this->resetPage(); }
|
||||
public function updatingFiltroFechaDesde(): void { $this->resetPage(); }
|
||||
public function updatingFiltroFechaHasta(): void { $this->resetPage(); }
|
||||
public function updatingFiltroMes(): void { $this->resetPage(); }
|
||||
|
||||
public function render()
|
||||
public function updatedFiltroMes(): void
|
||||
{
|
||||
$query = AiUsageLog::query()->latest();
|
||||
if ($this->filtroMes) {
|
||||
$this->filtroFechaDesde = '';
|
||||
$this->filtroFechaHasta = '';
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedFiltroFechaDesde(): void
|
||||
{
|
||||
if ($this->filtroFechaDesde) $this->filtroMes = '';
|
||||
}
|
||||
|
||||
public function updatedFiltroFechaHasta(): void
|
||||
{
|
||||
if ($this->filtroFechaHasta) $this->filtroMes = '';
|
||||
}
|
||||
|
||||
private function applyFiltros($query): void
|
||||
{
|
||||
if ($this->filtroServicio) {
|
||||
$query->where('servicio', $this->filtroServicio);
|
||||
}
|
||||
if ($this->filtroCanal) {
|
||||
$query->where('canal', $this->filtroCanal);
|
||||
}
|
||||
if ($this->filtroFechaDesde) {
|
||||
$query->whereDate('created_at', '>=', $this->filtroFechaDesde);
|
||||
}
|
||||
if ($this->filtroFechaHasta) {
|
||||
$query->whereDate('created_at', '<=', $this->filtroFechaHasta);
|
||||
if ($this->filtroMes) {
|
||||
$inicio = Carbon::createFromFormat('Y-m', $this->filtroMes)->startOfMonth();
|
||||
$fin = $inicio->copy()->endOfMonth();
|
||||
$query->whereBetween('created_at', [$inicio, $fin]);
|
||||
} else {
|
||||
if ($this->filtroFechaDesde) {
|
||||
$query->whereDate('created_at', '>=', $this->filtroFechaDesde);
|
||||
}
|
||||
if ($this->filtroFechaHasta) {
|
||||
$query->whereDate('created_at', '<=', $this->filtroFechaHasta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$query = AiUsageLog::query()->latest();
|
||||
$this->applyFiltros($query);
|
||||
$logs = $query->paginate(30);
|
||||
|
||||
// Resumen total (aplicando mismos filtros sin paginación)
|
||||
$resumenQuery = AiUsageLog::query();
|
||||
if ($this->filtroServicio) $resumenQuery->where('servicio', $this->filtroServicio);
|
||||
if ($this->filtroCanal) $resumenQuery->where('canal', $this->filtroCanal);
|
||||
if ($this->filtroFechaDesde) $resumenQuery->whereDate('created_at', '>=', $this->filtroFechaDesde);
|
||||
if ($this->filtroFechaHasta) $resumenQuery->whereDate('created_at', '<=', $this->filtroFechaHasta);
|
||||
$this->applyFiltros($resumenQuery);
|
||||
|
||||
$resumen = $resumenQuery->selectRaw("
|
||||
COUNT(*) as total_llamadas,
|
||||
@@ -56,9 +86,18 @@ class ShowAiLogs extends Component
|
||||
SUM(output_tokens) as total_output_tokens,
|
||||
SUM(audio_segundos) as total_segundos_whisper,
|
||||
SUM(CASE WHEN servicio = 'whisper' THEN costo ELSE 0 END) as costo_whisper,
|
||||
SUM((COALESCE(input_tokens,0) + COALESCE(output_tokens,0)) / 1000000.0 * 20000) as costo_gemini,
|
||||
AVG(tiempo_ms) as avg_tiempo_ms
|
||||
")->first();
|
||||
|
||||
return view('livewire.chat.show-ai-logs', compact('logs', 'resumen'));
|
||||
$meses = collect(range(0, 12))->map(function ($i) {
|
||||
$d = now()->subMonths($i);
|
||||
return [
|
||||
'value' => $d->format('Y-m'),
|
||||
'label' => ucfirst($d->locale('es')->isoFormat('MMMM YYYY')),
|
||||
];
|
||||
});
|
||||
|
||||
return view('livewire.chat.show-ai-logs', compact('logs', 'resumen', 'meses'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user