@extends('layouts.app') @section('content') @php $winnerVariantId = (int) ($test->winner_variant_id ?? 0); $finalVariant = $test->variants->firstWhere('variant_type', 'final'); $testVariants = $test->variants->where('variant_type', 'test')->values(); $hasWinner = $winnerVariantId > 0; $canLaunchFinal = $hasWinner && $finalVariant && !$finalVariant->campaign_send_id; $winnerLabel = $test->winnerVariant?->variant_name ?: (\App\Support\AbTestingSupport::winnerMetrics()[$test->winner_metric] ?? $test->winner_metric); $startSummary = $test->scheduled_at ? \App\Support\CampaignBuilderSupport::scheduleSummary((string) $test->getRawOriginal('scheduled_at'), $test->scheduled_timezone) : 'Manual / instantaneo'; $cadenceSummary = \App\Support\AbTestingSupport::intervalSummary((int) $test->send_interval_value, (string) $test->send_interval_unit); $finalDelaySummary = \App\Support\AbTestingSupport::intervalSummary((int) $test->final_delay_value, (string) $test->final_delay_unit); $metrics = collect($variantMetrics); $sentTotal = (int) $metrics->sum('sent_count'); $failedTotal = (int) $metrics->sum('failed_count'); $skippedTotal = (int) $metrics->sum('skipped_count'); $opensTotal = (int) $metrics->sum('unique_opens'); $clicksTotal = (int) $metrics->sum('unique_clicks'); $unsubTotal = (int) $metrics->sum('unsubscribes'); $openRate = $sentTotal > 0 ? round(($opensTotal / $sentTotal) * 100, 2) : 0; $clickRate = $sentTotal > 0 ? round(($clicksTotal / $sentTotal) * 100, 2) : 0; $preflight = collect($launchReadiness); $readyDrafts = $preflight->filter(static fn ($row): bool => (bool) ($row['ready'] ?? false))->count(); $blockedVariants = $preflight->filter(static fn ($row): bool => !(bool) ($row['ready'] ?? false))->count(); $blockersTotal = (int) $preflight->sum(static fn ($row): int => count((array) ($row['blockers'] ?? []))); $includeLists = $test->audienceLists->filter(static fn ($list): bool => (string) $list->pivot->mode === 'include')->values(); $excludeLists = $test->audienceLists->filter(static fn ($list): bool => (string) $list->pivot->mode === 'exclude')->values(); $includeLabel = $includeLists->pluck('name')->take(3)->implode(', '); $excludeLabel = $excludeLists->pluck('name')->take(2)->implode(', '); if ($includeLists->count() > 3) { $includeLabel .= ' +' . ($includeLists->count() - 3); } if ($excludeLists->count() > 2) { $excludeLabel .= ' +' . ($excludeLists->count() - 2); } $includeLabel = $includeLabel !== '' ? $includeLabel : 'Sin include'; $excludeLabel = $excludeLabel !== '' ? $excludeLabel : 'Sin exclude'; $finalAudience = $finalVariant ? (int) $finalVariant->sample_size : max(0, (int) $test->source_audience_total - ((int) $test->variant_count * (int) $test->sample_size_per_variant)); $testRates = $testVariants ->map(static fn ($variant): int => (int) ($variant->campaign?->send_rate_per_minute ?? 0)) ->filter(static fn (int $rate): bool => $rate > 0) ->values(); $minSps = $testRates->isNotEmpty() ? (int) $testRates->min() : 0; $maxSps = $testRates->isNotEmpty() ? (int) $testRates->max() : 0; $avgSps = $testRates->isNotEmpty() ? round((float) $testRates->avg(), 1) : 0; @endphp
#{{ $test->id }}

{{ $test->name }}

{{ $test->status }}

{{ $test->sourceCampaign?->name ?: 'Sin campana base' }} {{ $includeLabel }} {{ number_format((int) $test->source_audience_total) }} evaluados

Resultados
@csrf
@csrf
@csrf
Pruebas {{ number_format((int) $test->variant_count) }} x {{ number_format((int) $test->sample_size_per_variant) }}
Final {{ number_format($finalAudience) }}
Inicio {{ $startSummary }}
Cadencia {{ $cadenceSummary }}
SPS / rate {{ $minSps === $maxSps ? number_format($maxSps) : number_format($minSps) . '-' . number_format($maxSps) }} prom {{ number_format((float) $avgSps, 1) }}
Espera final {{ $finalDelaySummary }}
Preflight {{ $blockersTotal > 0 ? number_format($blockersTotal) . ' bloqueos' : number_format($readyDrafts) . ' listos' }} @if ($blockedVariants > 0) {{ number_format($blockedVariants) }} variantes @endif
Enviados {{ number_format($sentTotal) }} {{ number_format($failedTotal) }} fallidos / {{ number_format($skippedTotal) }} omitidos
Opens {{ number_format($opensTotal) }} | {{ $openRate }}%
Clicks {{ number_format($clicksTotal) }} | {{ $clickRate }}%
Ganador {{ $winnerLabel }}
Include: {{ $includeLabel }} Exclude: {{ $excludeLabel }} Aliases: {{ number_format($test->variants->count()) }} Unsubs: {{ number_format($unsubTotal) }}
@csrf
@csrf
@csrf
@csrf @method('DELETE')

Variantes y final

{{ number_format($testVariants->count()) }} pruebas, {{ $finalVariant ? '1 final' : 'sin final' }}, {{ number_format($sentTotal) }} enviados.

{{ $test->created_at?->format('Y-m-d') }} {{ $test->scheduled_timezone }}
@foreach ($test->variants as $variant) @php $metrics = $variantMetrics[(int) $variant->campaign_id] ?? [ 'total_recipients' => 0, 'sent_count' => 0, 'failed_count' => 0, 'skipped_count' => 0, 'unique_opens' => 0, 'unique_clicks' => 0, 'unsubscribes' => 0, 'open_rate' => 0, 'click_rate' => 0, 'ctor_rate' => 0, 'unsubscribe_rate' => 0, 'latest_send' => null, ]; $readiness = $launchReadiness[(int) $variant->id] ?? null; $latestSend = $metrics['latest_send'] ?? null; $isWinner = $winnerVariantId === (int) $variant->id; $isFinal = (string) $variant->variant_type === 'final'; $totalRecipients = (int) ($metrics['total_recipients'] ?: ($latestSend->total_recipients ?? 0)); $sentCount = (int) $metrics['sent_count']; $progress = $totalRecipients > 0 ? min(100, round(($sentCount / max(1, $totalRecipients)) * 100, 2)) : 0; $blockers = (array) ($readiness['blockers'] ?? []); $sendRate = (int) ($latestSend->rate_per_minute ?? $variant->campaign?->send_rate_per_minute ?? 0); $timezone = (string) ($test->scheduled_timezone ?: ($variant->campaign?->scheduled_timezone ?? 'America/Tijuana')); $variantOrder = (int) ($variant->send_order ?: ($loop->iteration ?? 0)); $pendingBefore = $testVariants->filter(static function ($candidate) use ($variant, $variantMetrics): bool { if ((int) ($candidate->send_order ?? 0) >= (int) ($variant->send_order ?? 0)) { return false; } $candidateSend = $variantMetrics[(int) $candidate->campaign_id]['latest_send'] ?? null; $candidateStatus = (string) ($candidateSend->status ?? ''); return !in_array($candidateStatus, ['completed', 'sent', 'failed', 'cancelled'], true); })->count(); $scheduledAtRaw = trim((string) ( $latestSend->scheduled_at ?? $variant->getRawOriginal('scheduled_at') ?? $variant->campaign?->getRawOriginal('scheduled_at') ?? '' )); $sendCreatedRaw = trim((string) ($latestSend->created_at ?? '')); $sendStartedRaw = trim((string) ($latestSend->started_at ?? '')); $sendLastProcessedRaw = trim((string) ($latestSend->last_processed_at ?? '')); $sendUpdatedRaw = trim((string) ($latestSend->updated_at ?? '')); $sendStatus = (string) ($latestSend->status ?? ''); $sendCreatedLabel = $sendCreatedRaw !== '' ? \Illuminate\Support\Carbon::parse($sendCreatedRaw, 'UTC')->setTimezone($timezone)->format('Y-m-d H:i') : ''; $sendStartedLabel = $sendStartedRaw !== '' ? \Illuminate\Support\Carbon::parse($sendStartedRaw, 'UTC')->setTimezone($timezone)->format('H:i') : ''; $sendLastLabel = ($sendLastProcessedRaw !== '' || $sendUpdatedRaw !== '') ? \Illuminate\Support\Carbon::parse($sendLastProcessedRaw !== '' ? $sendLastProcessedRaw : $sendUpdatedRaw, 'UTC')->setTimezone($timezone)->format('H:i') : ''; $scheduledLocalLabel = $scheduledAtRaw !== '' ? \Illuminate\Support\Carbon::parse($scheduledAtRaw, 'UTC')->setTimezone($timezone)->format('Y-m-d H:i') : ''; $scheduleLabel = match (true) { in_array($sendStatus, ['completed', 'sent'], true) => 'Completada', $sendStatus === 'running' => 'Enviando', $sendStatus === 'queued' => 'En cola', $scheduledAtRaw !== '' => 'Agendada', $latestSend || $variant->campaign_send_id => 'Inmediato', default => 'Sin programar', }; $displayStatus = $sendStatus !== '' ? $sendStatus : (string) $variant->status; $scheduleMeta = 'turno ' . number_format($variantOrder) . '/' . number_format($testVariants->count()); if ($pendingBefore > 0) { $scheduleMeta .= ' - espera ' . number_format($pendingBefore) . ' antes'; } $scheduleDetail = match (true) { in_array($sendStatus, ['completed', 'sent'], true) && $sendLastLabel !== '' => 'fin ' . $sendLastLabel, $sendStatus === 'running' && $sendStartedLabel !== '' => 'inicio ' . $sendStartedLabel, $scheduledLocalLabel !== '' => 'agenda ' . $scheduledLocalLabel, $sendStartedLabel !== '' => 'inicio ' . $sendStartedLabel, $sendCreatedLabel !== '' && $sendStatus === 'queued' => 'sin agenda real', default => $timezone, }; $scheduleLast = $sendLastLabel !== '' ? 'ultimo ' . $sendLastLabel : ($scheduledLocalLabel !== '' ? $timezone : ''); @endphp $isWinner])> @endforeach
Variante Subject / campana Lista Hora SPS Progreso Opens Clicks Estado Acciones
$isFinal])>{{ $isFinal ? 'FINAL' : $variant->variant_key }}
{{ $variant->variant_name }} @if ($isWinner) Ganadora @endif {{ number_format((int) $variant->sample_size) }} contactos
@if ($variant->campaign) {{ $variant->campaign->name }} {{ $variant->campaign->subject ?: 'Sin subject' }} @if ($variant->campaign->preheader) {{ $variant->campaign->preheader }} @endif @else Sin campana @endif @if ($variant->list) {{ $variant->list->name }} {{ number_format((int) $variant->list->active_contacts_count) }} activos @else Sin lista @endif
{{ $scheduleLabel }} {{ $scheduleMeta }} {{ $scheduleDetail }} @if ($scheduleLast !== '') {{ $scheduleLast }} @endif
@if ($sendRate > 0)
{{ number_format($sendRate) }} emails/seg
@else Sin rate @endif
@if ($totalRecipients > 0 || $sentCount > 0)
{{ number_format($sentCount) }} / {{ number_format($totalRecipients) }} @if ((int) $metrics['failed_count'] > 0 || (int) $metrics['skipped_count'] > 0) {{ number_format((int) $metrics['failed_count']) }} fallidos / {{ number_format((int) $metrics['skipped_count']) }} omitidos @endif
@elseif ($readiness)
{{ ($readiness['ready'] ?? false) ? 'Listo para lanzar' : count($blockers) . ' bloqueos preflight' }} @if ($blockers) {{ $blockers[0] }} @endif
@else Sin envio @endif
{{ $metrics['open_rate'] }}% {{ number_format((int) $metrics['unique_opens']) }} {{ $metrics['click_rate'] }}% {{ number_format((int) $metrics['unique_clicks']) }} CTOR {{ $metrics['ctor_rate'] }}% {{ $displayStatus }} @if ($latestSend) Send #{{ $latestSend->id }} @elseif ($variant->campaign_send_id) Send #{{ $variant->campaign_send_id }} @endif
@if ($variant->variant_type === 'test')
@csrf
@endif @if ($variant->campaign) @endif
@endsection