info('Verificando paquetes por vencer...'); $this->newLine(); $customDays = $this->option('days'); $testMode = $this->option('test'); if ($testMode) { $this->warn('MODO TEST'); $this->newLine(); } if ($customDays !== null) { $this->info("Usando días personalizados: {$customDays}"); } else { $this->info("Periodo de paquete:"); $this->line(" • Paquetes de 30 días → Notificar 7 días antes"); $this->line(" • Paquetes de 15 días → Notificar 3 días antes"); $this->line(" • Paquetes de 7 días → Notificar 2 días antes"); } $this->newLine(); $activePackages = PackSim::with(['package', 'simCard.clientSims.client']) ->where('is_active', true) ->whereNotNull('activated_at') ->get(); $this->info("Paquetes activos: {$activePackages->count()}"); $this->newLine(); $notificationsSent = 0; $packagesChecked = 0; if ($this->option('show-all')) { $this->showAllPackages($activePackages); return Command::SUCCESS; } $now = Carbon::now()->startOfDay(); foreach ($activePackages as $packSim) { $packagesChecked++; $activatedAt = Carbon::parse($packSim->activated_at); $expirationDate = $activatedAt->copy()->addDays($packSim->package->period); $expirationDateStart = $expirationDate->copy()->startOfDay(); if ($expirationDateStart->isFuture()) { $daysRemaining = (int) $now->diffInDays($expirationDateStart, false); } elseif ($expirationDateStart->isToday()) { $daysRemaining = 0; } else { // Ya expiró, saltar continue; } $shouldNotify = $this->shouldNotifyForPackage( $packSim->package->period, $daysRemaining, $customDays ); if ($shouldNotify) { $clientRelation = $packSim->simCard->activeClient()->first(); $client = $clientRelation; if (!$client) { $this->warn("SIM {$packSim->simCard->iccid} sin cliente activo"); continue; } if ($testMode) { $this->displayNotificationDetails($client, $packSim, $daysRemaining); } else { $this->sendWhatsAppNotification($client, $packSim, $daysRemaining); } $notificationsSent++; } } $this->newLine(); $this->info('Resumen'); $this->table( ['Métrica', 'Valor'], [ ['Paquetes revisados', $packagesChecked], ['Notificaciones enviadas', $notificationsSent], ['Modo', $testMode ? 'TEST' : 'PRODUCCIÓN'], ] ); return Command::SUCCESS; } private function shouldNotifyForPackage($packagePeriod, $daysRemaining, $customDays = null) { if ($customDays !== null) { $notificationDays = array_map('intval', explode(',', $customDays)); return in_array($daysRemaining, $notificationDays); } switch ($packagePeriod) { case 30: return $daysRemaining === 7; case 15: return $daysRemaining === 3; case 7: return $daysRemaining === 2; default: return false; } } private function sendWhatsAppNotification($client, $packSim, $daysRemaining) { $this->warn('PRODUCCIÓN: Aquí se enviaría la notificación real por WhatsApp'); $this->displayNotificationDetails($client, $packSim, $daysRemaining); } private function displayNotificationDetails($client, $packSim, $daysRemaining) { $activatedAt = Carbon::parse($packSim->activated_at); $expirationDate = $activatedAt->copy()->addDays($packSim->package->period); $this->line('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); $this->info(" NOTIFICACIÓN A ENVIAR:"); $this->line(" Cliente: {$client->full_name}"); $this->line(" Teléfono: {$client->phone}"); $this->line(" Email: {$client->email}"); $this->line(" Paquete: {$packSim->package->name} ({$packSim->package->period} días)"); $this->line(" SIM (ICCID): {$packSim->simCard->iccid}"); $this->line(" Activado: " . $activatedAt->format('d/m/Y')); $this->line(" Vence el: " . $expirationDate->format('d/m/Y')); $this->line(" Días restantes: {$daysRemaining} día(s)"); $this->line('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); $this->newLine(); } private function showAllPackages($packages) { $this->info('Mostrando todos los paquetes activos con sus fechas de vencimiento:'); $this->newLine(); $data = []; $now = Carbon::now()->startOfDay(); foreach ($packages as $packSim) { $activatedAt = Carbon::parse($packSim->activated_at); $expirationDate = $activatedAt->copy()->addDays($packSim->package->period); $expirationDateStart = $expirationDate->copy()->startOfDay(); // ✅ CORRECCIÓN: Calcular días restantes correctamente if ($expirationDateStart->isFuture()) { $daysRemaining = (int) $now->diffInDays($expirationDateStart, false); } elseif ($expirationDateStart->isToday()) { $daysRemaining = 0; } else { $daysRemaining = -1; // Expirado } $clientRelation = $packSim->simCard->activeClient()->first(); $clientName = $clientRelation ? $clientRelation->full_name : 'Sin cliente activo'; $data[] = [ 'Cliente' => $clientName, 'Paquete' => $packSim->package->name, 'SIM (ICCID)' => $packSim->simCard->iccid, 'Activado' => $activatedAt->format('d/m/Y'), 'Vence el' => $expirationDate->format('d/m/Y'), 'Días restantes' => $daysRemaining >= 0 ? $daysRemaining : 'Expirado', ]; } $this->table( ['Cliente', 'Paquete', 'SIM (ICCID)', 'Activado', 'Vence el', 'Días restantes'], $data ); } }