FIX: Ajustar cálculo de días restantes para paquetes en el command y controlador

This commit is contained in:
Juan Felipe Zapata Moreno 2025-11-18 23:44:21 -06:00
parent 1523cd408d
commit 1ae0dd6b0c
4 changed files with 39 additions and 46 deletions

View File

@ -6,38 +6,25 @@
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Console\Command; use Illuminate\Console\Command;
/**
*
*/
class CheckExpiringPackages extends Command class CheckExpiringPackages extends Command
{ {
/**
* Nombre del comando
*/
protected $signature = 'packages:check-expiring protected $signature = 'packages:check-expiring
{--days= : Días de anticipación para notificar} {--days= : Días de anticipación para notificar}
{--test : Modo de prueba } {--test : Modo de prueba }
{--show-all : Mostrar todos los paquetes con sus fechas de vencimiento}'; {--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'; protected $description = 'Verificar paquetes por vencer y enviar notificaciones a los usuarios';
/**
* Ejecutar comando
*/
public function handle() public function handle()
{ {
$this->info('Verificando paquetes por vencer...'); $this->info('Verificando paquetes por vencer...');
$this->newLine(); $this->newLine();
// Obtener configuración
$customDays = $this->option('days'); $customDays = $this->option('days');
$testMode = $this->option('test'); $testMode = $this->option('test');
if ($testMode) { if ($testMode) {
$this->warn('TEST'); $this->warn('MODO TEST');
$this->newLine(); $this->newLine();
} }
@ -51,13 +38,12 @@ public function handle()
} }
$this->newLine(); $this->newLine();
// Obtener paquetes activos con sus relaciones
$activePackages = PackSim::with(['package', 'simCard.clientSims.client']) $activePackages = PackSim::with(['package', 'simCard.clientSims.client'])
->where('is_active', true) ->where('is_active', true)
->whereNotNull('activated_at') ->whereNotNull('activated_at')
->get(); ->get();
$this->info("paquetes activos: {$activePackages->count()}"); $this->info("Paquetes activos: {$activePackages->count()}");
$this->newLine(); $this->newLine();
$notificationsSent = 0; $notificationsSent = 0;
@ -68,17 +54,24 @@ public function handle()
return Command::SUCCESS; return Command::SUCCESS;
} }
$now = Carbon::now()->startOfDay();
foreach ($activePackages as $packSim) { foreach ($activePackages as $packSim) {
$packagesChecked++; $packagesChecked++;
// Calcular fecha de vencimiento
$activatedAt = Carbon::parse($packSim->activated_at); $activatedAt = Carbon::parse($packSim->activated_at);
$expirationDate = $activatedAt->copy()->addDays($packSim->package->period); $expirationDate = $activatedAt->copy()->addDays($packSim->package->period);
$expirationDateStart = $expirationDate->copy()->startOfDay();
// Días restantes if ($expirationDateStart->isFuture()) {
$daysRemaining = (int) now()->diffInDays($expirationDate, false); $daysRemaining = (int) $now->diffInDays($expirationDateStart, false);
} elseif ($expirationDateStart->isToday()) {
$daysRemaining = 0;
} else {
// Ya expiró, saltar
continue;
}
// Determinar si debe notificar según el periodo del paquete
$shouldNotify = $this->shouldNotifyForPackage( $shouldNotify = $this->shouldNotifyForPackage(
$packSim->package->period, $packSim->package->period,
$daysRemaining, $daysRemaining,
@ -86,7 +79,6 @@ public function handle()
); );
if ($shouldNotify) { if ($shouldNotify) {
// Obtener cliente activo
$clientRelation = $packSim->simCard->activeClient()->first(); $clientRelation = $packSim->simCard->activeClient()->first();
$client = $clientRelation; $client = $clientRelation;
@ -95,11 +87,9 @@ public function handle()
continue; continue;
} }
// Mostrar información
if ($testMode) { if ($testMode) {
$this->displayNotificationDetails($client, $packSim, $daysRemaining); $this->displayNotificationDetails($client, $packSim, $daysRemaining);
} else { } else {
// notificacion real
$this->sendWhatsAppNotification($client, $packSim, $daysRemaining); $this->sendWhatsAppNotification($client, $packSim, $daysRemaining);
} }
@ -121,40 +111,25 @@ public function handle()
return Command::SUCCESS; return Command::SUCCESS;
} }
/**
* Determina si se debe notificar según el periodo del paquete y días restantes
*/
private function shouldNotifyForPackage($packagePeriod, $daysRemaining, $customDays = null) private function shouldNotifyForPackage($packagePeriod, $daysRemaining, $customDays = null)
{ {
// Si se especificaron días personalizados
if ($customDays !== null) { if ($customDays !== null) {
$notificationDays = array_map('intval', explode(',', $customDays)); $notificationDays = array_map('intval', explode(',', $customDays));
return in_array($daysRemaining, $notificationDays); return in_array($daysRemaining, $notificationDays);
} }
// Lógica según el periodo del paquete
switch ($packagePeriod) { switch ($packagePeriod) {
case 30: case 30:
// Paquetes de 30 días: notificar a los 7 días
return $daysRemaining === 7; return $daysRemaining === 7;
case 15: case 15:
// Paquetes de 15 días: notificar a los 3 días
return $daysRemaining === 3; return $daysRemaining === 3;
case 7: case 7:
// Paquetes de 7 días: notificar a los 2 días
return $daysRemaining === 2; return $daysRemaining === 2;
default: default:
// Para otros periodos, no notificar (o puedes ajustar la lógica)
return false; return false;
} }
} }
/**
* Envía notificación por WhatsApp (temporal: solo muestra en consola)
*/
private function sendWhatsAppNotification($client, $packSim, $daysRemaining) private function sendWhatsAppNotification($client, $packSim, $daysRemaining)
{ {
$this->warn('PRODUCCIÓN: Aquí se enviaría la notificación real por WhatsApp'); $this->warn('PRODUCCIÓN: Aquí se enviaría la notificación real por WhatsApp');
@ -180,18 +155,27 @@ private function displayNotificationDetails($client, $packSim, $daysRemaining)
$this->newLine(); $this->newLine();
} }
private function showAllPackages($packages) private function showAllPackages($packages)
{ {
$this->info('Mostrando todos los paquetes activos con sus fechas de vencimiento:'); $this->info('Mostrando todos los paquetes activos con sus fechas de vencimiento:');
$this->newLine(); $this->newLine();
$data = []; $data = [];
$now = Carbon::now()->startOfDay();
foreach ($packages as $packSim) { foreach ($packages as $packSim) {
$activatedAt = Carbon::parse($packSim->activated_at); $activatedAt = Carbon::parse($packSim->activated_at);
$expirationDate = $activatedAt->copy()->addDays($packSim->package->period); $expirationDate = $activatedAt->copy()->addDays($packSim->package->period);
$daysRemaining = (int) now()->diffInDays($expirationDate, false); $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(); $clientRelation = $packSim->simCard->activeClient()->first();
$clientName = $clientRelation ? $clientRelation->full_name : 'Sin cliente activo'; $clientName = $clientRelation ? $clientRelation->full_name : 'Sin cliente activo';
@ -202,7 +186,7 @@ private function showAllPackages($packages)
'SIM (ICCID)' => $packSim->simCard->iccid, 'SIM (ICCID)' => $packSim->simCard->iccid,
'Activado' => $activatedAt->format('d/m/Y'), 'Activado' => $activatedAt->format('d/m/Y'),
'Vence el' => $expirationDate->format('d/m/Y'), 'Vence el' => $expirationDate->format('d/m/Y'),
'Días restantes' => $daysRemaining, 'Días restantes' => $daysRemaining >= 0 ? $daysRemaining : 'Expirado',
]; ];
} }

View File

@ -91,7 +91,18 @@ public function expiring(Request $request)
// Calcular fecha de vencimiento // Calcular fecha de vencimiento
$activatedAt = Carbon::parse($packSim->activated_at); $activatedAt = Carbon::parse($packSim->activated_at);
$expirationDate = $activatedAt->copy()->addDays($packSim->package->period); $expirationDate = $activatedAt->copy()->addDays($packSim->package->period);
$daysRemaining = (int) now()->diffInDays($expirationDate, false);
$now = Carbon::now()->startOfDay();
$expirationDateStart = $expirationDate->copy()->startOfDay();
if ($expirationDateStart->isFuture()) {
$daysRemaining = (int) $now->diffInDays($expirationDateStart, false);
} elseif ($expirationDateStart->isToday()) {
$daysRemaining = 0;
} else {
// Ya expiró, no incluir
return null;
}
// Determinar si debe incluirse // Determinar si debe incluirse
$shouldInclude = $this->shouldIncludePackage( $shouldInclude = $this->shouldIncludePackage(

View File

@ -23,8 +23,6 @@ public function run(): void
$this->call(UserSeeder::class); $this->call(UserSeeder::class);
$this->call(SettingSeeder::class); $this->call(SettingSeeder::class);
$this->call(ClientSeeder::class); //$this->call(PackageSeeder::class);
$this->call(SimCardSeeder::class);
$this->call(PackageSeeder::class);
} }
} }

View File

@ -36,7 +36,7 @@
Route::resource('sales', SaleController::class); Route::resource('sales', SaleController::class);
Route::get('cash-closes', [CashCloseController::class, 'index']); Route::get('cash-closes', [CashCloseController::class, 'index']);
Route::put('cash-closes/close', [CashCloseController::class, 'CloseCashClose']); Route::put('cash-closes/close', [CashCloseController::class, 'closeCashClose']);
Route::get('cash-closes/report', [CashCloseController::class, 'report']); Route::get('cash-closes/report', [CashCloseController::class, 'report']);
Route::get('cash-closes/export', [CashCloseController::class, 'exportReport']); Route::get('cash-closes/export', [CashCloseController::class, 'exportReport']);
}); });