comment(Inspiring::quote()); })->purpose('Display an inspiring quote'); Artisan::command('reservations:expire', function (): void { $expired = app(ExpireStockReservationsService::class)->expireOverdue(); $this->info("Expired purchases: {$expired['purchases']}"); $this->info("Expired cart items: {$expired['cart_items']}"); })->purpose('Release expired stock reservations from purchases and abandoned carts'); Schedule::command('reservations:expire') ->everyMinute() ->withoutOverlapping(); Artisan::command( 'tenants:reset-transactions {tenant : Código del tenant que se limpiará} {--dry-run : Mostrar el alcance sin modificar datos} {--force : Omitir la confirmación interactiva}', function ( TenantTransactionResetService $resetService, AdminCredentialVerifier $adminCredentialVerifier, ): int { $tenantCode = (string) $this->argument('tenant'); try { $preview = $resetService->preview($tenantCode); } catch (InvalidArgumentException $exception) { $this->error($exception->getMessage()); return self::FAILURE; } $this->warn("Se eliminarán los datos transaccionales de: {$tenantCode}"); $this->table( ['Dato', 'Cantidad'], collect($preview)->map(fn (int $count, string $label): array => [$label, $count])->values(), ); $this->info('Los usuarios, el catálogo, los eventos y la configuración se conservarán.'); if ($this->option('dry-run')) { $this->comment('Vista previa finalizada; no se modificaron datos.'); return self::SUCCESS; } if (! $this->option('force') && ! $this->confirm('¿Confirmás esta limpieza irreversible?')) { $this->comment('Operación cancelada.'); return self::SUCCESS; } $this->newLine(); $this->warn('Autorización administrativa requerida.'); $adminEmail = (string) $this->ask('Email del administrador'); $adminPassword = (string) $this->secret('Contraseña del administrador'); if (! $adminCredentialVerifier->verify($adminEmail, $adminPassword)) { $this->error('Las credenciales no son válidas o el usuario no posee el rol admin.'); return self::FAILURE; } $summary = $resetService->reset($tenantCode); $this->info('Limpieza completada correctamente.'); $this->table( ['Resultado', 'Cantidad'], collect($summary)->map(fn (int $count, string $label): array => [$label, $count])->values(), ); return self::SUCCESS; }, )->purpose('Delete tenant sales, carts, tickets and reservations while preserving users and catalog');