Develop #4
154
app/Console/Commands/CheckExpiringPackages.php
Normal file
154
app/Console/Commands/CheckExpiringPackages.php
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\PackSim;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class CheckExpiringPackages extends Command
|
||||
{
|
||||
/**
|
||||
* Nombre del comando
|
||||
*/
|
||||
protected $signature = 'packages:check-expiring
|
||||
{--days=7,3,1 : Días de anticipación para notificar}
|
||||
{--test : Modo de prueba }
|
||||
{--show-all : Mostrar todos los paquetes con sus fechas de vencimiento}';
|
||||
|
||||
/**
|
||||
* La descripción del comando
|
||||
*/
|
||||
protected $description = 'Verificar paquetes por vencer y enviar notificaciones a los usuarios';
|
||||
|
||||
/**
|
||||
* Ejecutar comando
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->info('Verificando paquetes por vencer...');
|
||||
$this->newLine();
|
||||
|
||||
// Obtener configuración
|
||||
$notificationDays = array_map('intval', explode(',', $this->option('days')));
|
||||
$testMode = $this->option('test');
|
||||
|
||||
if ($testMode) {
|
||||
$this->warn('TEST');
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
// Obtener paquetes activos con sus relaciones
|
||||
$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;
|
||||
}
|
||||
|
||||
foreach ($activePackages as $packSim) {
|
||||
$packagesChecked++;
|
||||
|
||||
// Calcular fecha de vencimiento
|
||||
$activatedAt = Carbon::parse($packSim->activated_at);
|
||||
$expirationDate = $activatedAt->copy()->addDays($packSim->package->period);
|
||||
|
||||
// Días restante
|
||||
$daysRemaining = (int) now()->diffInDays($expirationDate, false);
|
||||
|
||||
// Verificar si debe notificar
|
||||
if (in_array($daysRemaining, $notificationDays)) {
|
||||
// Obtener cliente activo
|
||||
$clientRelation = $packSim->simCard->activeClient()->first();
|
||||
$client = $clientRelation;
|
||||
|
||||
if (!$client) {
|
||||
$this->warn("SIM {$packSim->simCard->iccid} sin cliente activo");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mostrar información
|
||||
if ($testMode) {
|
||||
$this->displayNotificationDetails($client, $packSim, $daysRemaining);
|
||||
} else {
|
||||
// notificacion real
|
||||
$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 displayNotificationDetails($client, $packSim, $daysRemaining)
|
||||
{
|
||||
$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}");
|
||||
$this->line(" SIM (ICCID): {$packSim->simCard->iccid}");
|
||||
$this->line(" Activado: " . Carbon::parse($packSim->activated_at)->format('d/m/Y'));
|
||||
$this->line(" Vence en: {$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 = [];
|
||||
|
||||
foreach ($packages as $packSim) {
|
||||
$activatedAt = Carbon::parse($packSim->activated_at);
|
||||
$expirationDate = $activatedAt->copy()->addDays($packSim->package->period);
|
||||
$daysRemaining = (int) now()->diffInDays($expirationDate, false);
|
||||
|
||||
$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,
|
||||
];
|
||||
}
|
||||
|
||||
$this->table(
|
||||
['Cliente', 'Paquete', 'SIM (ICCID)', 'Activado', 'Vence el', 'Días restantes'],
|
||||
$data
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -57,4 +57,22 @@ public function activePackage()
|
||||
->withTimestamps()
|
||||
->limit(1);
|
||||
}
|
||||
|
||||
public function clientSims()
|
||||
{
|
||||
return $this->hasMany(ClientSim::class, 'sim_card_id');
|
||||
}
|
||||
|
||||
public function activeClient()
|
||||
{
|
||||
return $this->belongsToMany(
|
||||
Client::class,
|
||||
'client_sims',
|
||||
'sim_card_id',
|
||||
'client_id'
|
||||
)->wherePivot('is_active', true)
|
||||
->withPivot('assigned_at', 'released_at', 'is_active')
|
||||
->withTimestamps()
|
||||
->limit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,3 +8,9 @@
|
||||
}
|
||||
|
||||
Schedule::call(new DeleteResetPasswords)->hourly();
|
||||
|
||||
Schedule::command('packages:check-expiring')
|
||||
->dailyAt('09:00')
|
||||
->timezone('America/Mexico_City')
|
||||
->withoutOverlapping()
|
||||
->appendOutputTo(storage_path('logs/packages-expiring.log'));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user